I am getting slightly different results on Windows (see below), but it looks like two things are happening on the Windows Command Prompt shell:
- the CMD shell strips out double quotes
- single quotes do not have special meaning in the command prompt shell: 'a b' is interpreted by the shell as two arguments: ['a] and [b']
I modified your program a bit to also print the raw args as they are passed by the command prompt shell to the Java process:
public class QuotingDemo implements Runnable {
@Option(names = "--json", description = "valid json")
String json;
@Override
public void run() {
System.out.println("JSON - " + json);
System.out.println("Args=" + Arrays.toString(args));
int exitCode = new CommandLine(new QuotingDemo()).execute(args);
System.out.println("Exitcode - " + exitCode);
}
}
On the Windows command prompt, I see this:
java -cp "c:\Users\remko\picocli-4.5.2.jar;." QuotingDemo --json='{"name": "value"}'
Args=[--json='{name:, value}']
Unmatched argument at index 1: 'value}''
Usage: <main class> [--json=<json>]
--json=<json> valid json
Exitcode - 2
Note that the raw args no longer contain double quotes, and the args array contains two elements: the first is --json='{name:, and the second is value}'.
Picocli then shows an error for the second argument (value}').
So, on the Windows command prompt, users can only quote using double quotes.
When the option parameter is quoted with double quotes in CMD prompt, the Java process receives a single argument (as intended):
java -cp "c:\Users\remko\picocli-4.5.2.jar;." QuotingDemo --json="{'name': 'value'}"
Args=[--json={'name': 'value'}]
The linux shell is more powerful and allows quoting with both single and double quotes.
On linux I see single quotes work as intended: the raw args array contains a single element:
java -cp /mnt/c/Users/remko/picocli-4.5.2.jar:. QuotingDemo --json='{"name": "value"}'
Args=[--json={"name": "value"}]
Similarly when the option parameter is quoted with double quotes:
java -cp /mnt/c/Users/remko/picocli-4.5.2.jar:. QuotingDemo --json="{'name': 'value'}"
Args=[--json={'name': 'value'}]