在 jsoncpp 中解析具有嵌套转义序列的引用字符串

Parsing Quoted Strings Having Nested Escape Sequences in jsoncpp

我在这里使用 jsoncpp 库。我对单引号')和双引号")的解析感到困惑。

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

为什么双引号必须像\\"而单引号必须是\'或只是',而不能是\\'

转义分隔符

\ 转义引号的原因是允许解析器区分引号是被引用的字符串中的字符,而定界引号是旨在关闭字符串。

众所周知,在C++语言中,双引号"用于分隔字符串。但是如果你想创建一个 包含 双引号 " 的字符串,\ 被用作转义符,因此 C++ 解析器知道解释以下内容字符作为 字符,而不是作为结束分隔符:

const std::string double_quote = """;     // WRONG!


const std::string double_quote = "\"";    // good


有两个解析器

在您的代码中,涉及两个解析器:C++ 解析器是将编译此代码的 C++ 编译器的一部分,JSON 解析器是 jsoncpp 库的一部分。 C++ 解析器在编译时解释此代码,而 jsoncpp 解析器在 运行 时间解释字符串。

和C++一样,JSON也使用双引号"来分隔字符串。 jsoncpp 解析器看到的一个简单 JSON 文档类似于:

{"name":"Xiaoying"}

要将此JSON文档括在C++字符串中,JSON文档中的双引号"需要用\进行转义,如下所示:

const std::string json_name = "{\"name\":\"Xiaoying\"}";    // good

这告诉 C++ 创建一个包含内容 {"name":"Xiaoying"} 的字符串。

嵌套分隔符

当 JSON 文档本身包含也必须转义的定界符时,事情开始变得复杂。与 C++ 一样,JSON 也使用反斜杠 \ 作为转义符。现在的问题是,如何区分用作 jsoncpp 解析器转义的反斜杠 \ 和用作 C++ 解析器转义的反斜杠 \?这样做的方法是使用 双反斜杠 \ 序列,C++ 解析器将其翻译成字符串中的单个反斜杠 '\' 字符。单个反斜杠在 运行 时传递给 jsoncpp 解析器时,将在那时被解释为转义字符。

由于 JSON 中反斜杠的使用规则与 C++ 的规则不同,事情变得更加复杂。特别是,在 C++ 中,单引号 ' 可以用反斜杠转义(如 \'),但这在 JSON.

中不是合法模式

以下是对您提出的五个案例的解释:

1. json_str1

C++ 语句

const std::string json_str1 = "{\"name\":\"Say \\"Hello\\"!\"}";

生成一个 JSON 文档,看起来像

{"name":"Say \"Hello\"!"}

当 jsoncpp 解析器看到这个时,它会通过反斜杠知道 "Say \"Hello\"!" 意味着这是一个包含 Say "Hello"! 的字符串

2。 json_str2

C++ 语句

const std::string json_str2 = "{\"name\":\"Say \"Hello\"!\"}";

生成一个 JSON 文档,看起来像

{"name":"Say "Hello"!"}

由于"Hello"两边的引号没有转义,所以jsoncpp解析器会失败。

3。 json_str3

C++ 语句

const std::string json_str3 = "{\"name\":\"Say \\'hi\\'!\"}";

生成一个 JSON 文档,看起来像

{"name":"Say \'hi\'!"}

由于 \' 模式在 JSON 中无法识别,这将在 jsoncpp 解析器中失败。

4. json_str4

C++ 语句

const std::string json_str4 = "{\"name\":\"Say \'hi\'!\"}";

生成一个 JSON 文档,看起来像

{"name":"Say 'hi'!"}

这是因为 C++ 解析器将 \' 序列解释为单个 ' 字符。

5. json_str5

C++ 语句

const std::string json_str5 = "{\"name\":\"Say 'hi'!\"}";

生成一个 JSON 文档,看起来像

{"name":"Say 'hi'!"}


另见

对于 C++ 转义序列规则:http://en.cppreference.com/w/cpp/language/escape

对于 JSON 转义序列规则:http://www.json.org/