BOOST生成JSON中文乱码

最近Linux生产环境在用boost库生成json的时候发现中文乱码,经调测发现是boost库的bug,在此记录。

boost生成Json

一般用法

boost有两个数据结构,其中一个是 property::ptree, 这个数据结构可以表示 xml json ini 等格式的文件内容,在不使用第三方比如 jsonpp 等库的情况下,在使用boost的情况下也不需要引入其他库,一般操作完 ptree 之后按 json 格式输出就行。

boost::property_tree::ptree pt;
pt.put("code", code);
pt.put("desc", desc);
const boost::property_tree::ptree data;
pt.put_child("data", data);

std::stringstream ss;
boost::property_tree::write_json(ss, pt, false);

但是在使用低版本的时候(我使用的是1.53版本),偶然使用到中文的时候,输出内容竟然是 \uxxxx 这样的编码,但事实上输入的中文确实是要求的UTF-8编码,有些人说使用 wptree,但我们并没有使用宽字符,而且由于本地调试的时候没有问题(本地版本较高),最终发现是该库的一个BUG。

原因分析

具体来说,在文件 boost/property_tree/json_parser/detail/write.hpp 中的 create_escapes 函数中,在低版本的实现中(具体是哪个版本修复的没有去追查),在编码的时候大概是下面的代码

if (*b == 0x20 || *b == 0x21 || (*b >= 0x23 && *b <= 0x2E) ||
(*b >= 0x30 && *b <= 0x5B) || (*b >= 0x5D && *b <= 0xFF))

这个代码的意思是判断是否需要编码的逻辑,其中 *b 其实就是 char,特别需要主要的是比较是不成立的。

为什么!

如果你了解UTF8字符集大概就明白了,字符集编码范围,举例说明,中文 的编码是 0xe4 0xbd 0xa0 咋一看好像是符合上面的条件,但是注意 char 的范围,因此这几个字节值以 char 类型表示的时候就变成了负数了,上面的条件是不成立的。

知道了为什么,改起来就很方便了,包括其后续的版本的修复也是一样的

typedef typename make_unsigned<Ch>::type UCh;
UCh c(*b);
if (c == 0x20 || c == 0x21 || (c >= 0x23 && c <= 0x2E) ||
(c >= 0x30 && c <= 0x5B) || (c >= 0x5D && c <= 0xFF))

当然也可以升级高版本解决。

最近的文章

BOOST不支持JSON输出数字值

前文刚讲述过boost的porperty_tree在JSON上的一些问题,最近使用又发现一些问题,可能大家都可能发现了,就是用该库来生成JSON的时候,不支持数字等非字符串类型的值。 …

技术 继续阅读
更早的文章

拼接YUV420P图像

最近需要实现视频的左右拼接,从而可以实现2路摄像头的同时显示,调研使用了几种实现方式进行了对比。 ffmpeg方式谈到视频方面的处理,肯定首选 ffmpeg,想要实现上面的功能,其实 ffmpeg 就能实现,使用其 filter 就可以,大概思路是: 使用 pad 扩展出另外一个图像的空间 使用 …

技术 继续阅读