将json中的utf8实体解码为utf8 C ++

时间:2016-11-24 19:14:42

标签: c++ json c++11 utf-8

我有一个带有utf8实体的字符串(我不确定我是否正确命名):

std::string std = "\u0418\u043d\u0434\u0435\u043a\u0441";

我怎么能把它转换成更具可读性的东西?我使用g ++和C ++ 11支持,但经过几个小时的挖掘std :: codecvt手册我得不到结果:

std::string std = "\u0418\u043d\u0434\u0435\u043a\u0441";

wstring_convert<codecvt_utf8_utf16<char16_t>,char16_t> convert; 
string dest = convert.to_bytes(std); 

返回以:

开头的梦魇堆栈跟踪
error: no matching function for call to ‘std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>::to_bytes(std::string&)

我希望还有另一种方式。

2 个答案:

答案 0 :(得分:2)

首先,您对std::wstring_convert的使用是倒退的。您有一个UTF-8编码std::string,您想要转换为宽Unicode字符串。您收到编译器错误,因为to_bytes()未将std::string作为输入。它需要std::wstring_convert::wide_string作为输入(在您的情况下为std::u16string,因为您在专业化中使用了char16_t,因此您需要使用from_bytes()代替{ {1}}:

to_bytes()

现在,正如所说,JSON specification州的第9节:

  

9 String

     

字符串是用引号(U + 0022)包装的Unicode代码点序列。除了必须转义的字符外,所有字符都可以放在引号内:引号(U + 0022),反向固相(U + 005C)和控制字符U + 0000到U + 001F。某些字符有两个字符的转义序列表示。

     

std::string std = "\u0418\u043d\u0434\u0435\u043a\u0441"; std::wstring_convert<codecvt_utf8_utf16<char16_t>, char16_t> convert; std::u16string dest = convert.from_bytes(std); 表示引号字符(U + 0022)。

     

\"表示反向固相字符(U + 005C)。

     

\\表示固相字符(U + 002F)。

     

\/代表退格字符(U + 0008)。

     

\b表示换页符(U + 000C)。

     

\f代表换行符(U + 000A)。

     

\n表示回车符(U + 000D)。

     

\r表示字符制表符(U + 0009)。

     

因此,例如,只包含一个反向固相字符的字符串可以表示为&#34; \t&#34;。

     

任何代码点都可以表示为十六进制数。这个数字的含义由ISO / IEC 10646确定。如果代码点在基本多语言平面(U + 0000到U + FFFF)中,那么它可以表示为六个字符的序列:a反向实线,后跟小写字母\\,后跟四个编码代码点的十六进制数字。十六进制数字可以是数字(U + 0030到U + 0039)或十六进制字母uA大写(U + 0041到U + 0046)或小写(U + 0061到U + 0066) )。因此,例如,仅包含单个反向固相字符的字符串可以表示为&#34; F&#34;。

     

以下四个案例都产生相同的结果:

     

&#34; \u005C&#34;

     

&#34; \u002F&#34;

     

&#34; \u002f&#34;

     

&#34; \/&#34;

     

要转义不在基本多语种平面中的代码点,该字符将表示为十二个字符的序列,编码UTF-16代理项。因此,例如,仅包含G谱号字符(U + 1D11E)的字符串可以表示为&#34; /&#34;。

原始JSON数据本身可以用UTF-8(最常见的编码),UTF-16等编码。但无论使用何种编码,字符序列\uD834\uDD1E代表UTF-16代码序列"\u0418\u043d\u0434\u0435\u043a\u0441",这是Unicode字符串U+0418 U+043d U+0434 U+0435 U+043a U+0441

如果您使用实际的JSON解析器(例如JSON for Modern C++jsoncppRapidJSON等),它将为您解析UTF-16 codeunit值并返回可读的Unicode字符串

但是,如果您手动处理JSON数据,则必须手动解码任何"Индекс"\x转义序列。 \uXXXX无法为您做到这一点。它只能将JSON从std::wstring_convert转换为std::string / std::wstring,如果这样可以更轻松地解析数据。但是,您仍然需要单独解析JSON的内容

之后,如果需要,您可以使用std:::u16string将任何提取的std::wstring_convert / std::wstring字符串转换回UTF-8以节省内存。

答案 1 :(得分:0)

您看到的不是实体,而是代码点。您通过Unicode转义序列定义字符,编译器会自动将它们转换为UTF-8。将其转换为UTF-16的典型方法,反之亦然:

static std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
std::string ws2s(const std::wstring &wstr) {
  std::string narrow = converter.to_bytes(wstr);
  return narrow;
}

std::wstring s2ws(const std::string &str) {
  std::wstring wide = converter.from_bytes(str);
  return wide;
}

当然,您无法将原始字符串转换为另一个相同类型的字符串(std :: string),因为它无法容纳此类字符。这就是编译器首先将UTF-16代码转换为UTF-8的原因。