I'm using the jsoncpp library here. I am confused by the parsing of single quotation marks ('
) and double quotation marks ("
).
Json::Value root;
Json::Reader reader;
const std::string json_str1 = "{\"name\":\"Say \\\"Hello\\\"!\"}";
const std::string json_str2 = "{\"name\":\"Say \"Hello\"!\"}";
const std::string json_str3 = "{\"name\":\"Say \\\'hi\\\'!\"}";
const std::string json_str4 = "{\"name\":\"Say \'hi\'!\"}";
const std::string json_str5 = "{\"name\":\"Say 'hi'!\"}";
reader.parse(json_str1, root, false); // success
reader.parse(json_str2, root, false); // fail
reader.parse(json_str3, root, false); // fail
reader.parse(json_str4, root, false); // success
reader.parse(json_str5, root, false); // success
Why must double quotations be like \\\"
but single quotations must be \'
or just '
, but can't be \\\'
?
The reason for escaping quotation marks with \
is to allow the parser(s) to distinguish between a quotation mark that is intended to be a character within the quoted string, and a delimiting quotation mark that is intended to close the string.
As you know, in the C++ language, double-quotes "
are used to delimit character strings. But if you want to create a string that contains a double quotation mark "
, the \
is used as an escape so the C++ parser knows to interpret the following character as a character, not as the closing delimiter:
const std::string double_quote = """; // WRONG!
const std::string double_quote = "\""; // good
In your code, there are two parsers that are involved: the C++ parser that is part of the C++ compiler that will be compiling this code, and the JSON parser that is part of the jsoncpp library. The C++ parser interprets this code at compile time, while the jsoncpp parser interprets the strings at run time.
Like C++, JSON also uses double quotes "
to delimit strings. A simple JSON document as seen by the jsoncpp parser looks something like:
{"name":"Xiaoying"}
To enclose this JSON document into a C++ string, the double quotation marks "
within the JSON document need to be escaped with \
as follows:
const std::string json_name = "{\"name\":\"Xiaoying\"}"; // good
This tells C++ to create a string having the contents {"name":"Xiaoying"}
.
Things start to get complicated when the JSON document itself contains delimiters that must also be escaped. Like C++, JSON also uses the backslash \
as an escape. Now the question becomes, how to distinguish a backslash \
intended as an escape for the jsoncpp parser from a backslash \
intended as an escape for the C++ parser? The way to do this is to use a double backslash \\
sequence, which is translated by the C++ parser into a single backslash '\'
character within the string. That single backslash, when passed to the jsoncpp parser at runtime, will at that time be interpreted as an escape character.
Things are further complicated by the fact that the rules for use of the backslash in JSON are different than the rules for C++. In particular, in C++ single quotes '
may be escaped with a backslash (as in \'
), but this is not a legal pattern in JSON.
Here is an explanation for each of the five cases you presented:
1. json_str1
The C++ statement
const std::string json_str1 = "{\"name\":\"Say \\\"Hello\\\"!\"}";
produces a JSON document that looks like
{"name":"Say \"Hello\"!"}
When the jsoncpp parser sees this, it will know by the backslashes that "Say \"Hello\"!"
means this is a string containing Say "Hello"!
2. json_str2
The C++ statement
const std::string json_str2 = "{\"name\":\"Say \"Hello\"!\"}";
produces a JSON document that looks like
{"name":"Say "Hello"!"}
Since the quotation marks around "Hello"
are not escaped, the jsoncpp parser will fail.
3. json_str3
The C++ statement
const std::string json_str3 = "{\"name\":\"Say \\\'hi\\\'!\"}";
produces a JSON document that looks like
{"name":"Say \'hi\'!"}
Since the \'
pattern is not recognized in JSON, this will fail in the jsoncpp parser.
4. json_str4
The C++ statement
const std::string json_str4 = "{\"name\":\"Say \'hi\'!\"}";
produces a JSON document that looks like
{"name":"Say 'hi'!"}
This is because the C++ parser interpreted the \'
sequence as a single '
character.
5. json_str5
The C++ statement
const std::string json_str5 = "{\"name\":\"Say 'hi'!\"}";
produces a JSON document that looks like
{"name":"Say 'hi'!"}
For the C++ escape sequence rules: http://en.cppreference.com/w/cpp/language/escape
For the JSON escape sequence rules: http://www.json.org/