我正在用C ++编写JSON解析器,在解析JSON字符串时遇到问题:
JSON规范声明JSON字符串可以包含以下形式的unicode字符:
"here comes a unicode character: \u05d9 !"
我的JSON解析器尝试将JSON字符串映射到std::string
,因此通常,JSON字符串的一个字符变为std::string
的一个字符。但是对于那些unicode角色,我真的不知道该怎么做:
我应该将原始字节值放在我的std::string
中,如下所示:
std::string mystr;
mystr.push_back('\0x05');
mystr.push_back('\0xd9');
或者我应该用iconv
这样的库来解释这两个字符,并将UTF-8编码的结果存储在我的字符串中吗?
我应该使用std::wstring
存储所有字符吗?那么* {NIX操作系统上wchar_t
长4个字节的内容是什么?
我觉得我的解决方案有问题,但我不明白是什么。在那种情况下我该怎么办?
答案 0 :(得分:12)
经过一番挖掘并感谢H2CO3's comments和Philipp's comments,我终于明白了这应该如何运作:
阅读RFC4627,第3. Encoding
部分:
- 醇>
编码
JSON文本应以Unicode编码。默认编码为
UTF-8。由于JSON文本的前两个字符始终为ASCII 字符[RFC0020],可以确定是否为八位字节 流是UTF-8,UTF-16(BE或LE),或UTF-32(BE或LE) 在前四个八位字节中的空值模式。
00 00 00 xx UTF-32BE 00 xx 00 xx UTF-16BE xx 00 00 00 UTF-32LE xx 00 xx 00 UTF-16LE xx xx xx xx UTF-8
因此,看起来JSON八位字节流可以用UTF-8,UTF-16或UTF-32编码(在BE或LE变体中,最后两个)。
一旦明确,Section 2.5. Strings
解释了如何处理JSON字符串中的\uXXXX
值:
任何角色都可能被转义。如果角色在基本
中 多语言平面(U + 0000到U + FFFF),然后它可能是
表示为六个字符的序列:反向固相,然后是
用小写字母u,后跟四个十六进制数字 编码角色的代码点。十六进制字母A到
F可以是大写或小写。因此,例如,包含
的字符串 只有一个反向固相字符可以表示为
“\ u005C”。
对不在Basic Multilingual Plane中的字符进行更完整的解释。
转义不在Basic Multilingual中的扩展字符 平面,角色表示为十二个字符的序列,
编码UTF-16代理对。所以,例如,一个字符串
仅包含G谱号字符(U + 1D11E)可以表示为
“\ uD834 \ uDD1E”。
希望这有帮助。
答案 1 :(得分:2)
如果我是你,我会使用std :: string来存储UTF-8和UTF-8。 如果传入的JSON文本不包含任何\ uXXXX序列,则std :: string可以按原样使用,而不是任何转换。
当您解析\ uXXXX时,您可以简单地对其进行解码并将其转换为UTF-8,有效地将其视为真正的UTF-8字符 - 这就是大多数JSON解析器正在做的事情(libjson for肯定)。
当然,使用这种方法用\ uXXXX读取JSON并立即使用你的库将其转储回来可能会丢失\ uXXXX序列并用真正的UTF-8表示替换它们,但是谁真正关心?最终,净结果仍然完全相同。