我有一个代码通过COM变体传递一些utf-8编码的JSON字符串,特别是使用CComVariant。一切顺利,直到我的软件安装在日本用户的计算机上,我想他正在使用日语版的Windows 7.不知何故,Windows决定更改1个非ascii字符的字节序列并打破JSON格式。
组合问题:
"nić" (bytes: 0x22 0x6E 0x69 0xC4 0x87 0x22)
将它打包到CComVariant然后解压缩后,上面的字符串变为:
"niāE (bytes: 0x22 0x6E 0x69 0xC4 0x81 0x45)
即。合并ć"
成为āE
。
我的代码如下(简化版):
void get_json(VARIANT *out)
{
const std::string json = "\"nić\"";
CComVariant result = json.c_str();
result.Detach(out);
}
然后在代码的其他部分:
CComVariant varJson;
get_json(&varJson);
const std::string utf8json = std::string(CStringA(varJson));
// At this point utf8json is not the same as original json above
// and cannot be decoded properly by JSON parser.
似乎我在COM Variant中误解了CStringA的一些内容,并且在这里传递UTF-8字节并不安全。我不能用西欧的Windows版本重现这个问题,这与日文版本有所不同。
答案 0 :(得分:1)
评论中解释了这个问题。至于解决方案,因为您正在使用std
(还有很多其他解决方案),我建议您使用此答案中定义的widen
函数:Is this code safe using wstring with MultiByteToWideChar?
并将代码更改为:
CComVariant result = widen(json).c_str();
我们在调试器下检查一下。之前:
后:
现在,VARIANT(或它包含的BSTR)没问题。
注意,如果你需要一个来自这个VARIANT或BSTR的等效字节字符串(你真的吗?),不要用这样的破坏代码将它转换回来:std::string(CStringA(varJson))
再次使用反向等价物widen
的{{1}},基于WideCharToMultiByte
这次。
答案 1 :(得分:0)
我找到了两种方法来解决这个问题:
\u1234
这样的unicode-escape序列,因此请确保我的所有数据都是纯粹的ascii。由于向后兼容性的限制,我必须走第二条路线。