对json的爱恨情仇
本文回想了对json的爱恨情仇. C++有风险,使用需慎重.
本文相关代码在:http://download.csdn.net/detail/baihacker/7862785
当中的測试数据不在里面,由于这是项目开发中用到的,须要保密.
在工作时才接触json,看过简单介绍,语法简单,易于扩展,用起来是非常爽的事.和后端的一些交互也基本上都是用的json.在项目中用了第三方库:simple json,用起来也不亦乐乎.只是也吃过该库的亏:
1.忘了解析后的JSONValue应该delete掉;
2.simple json出来的当中的数字用double表示,可是server给的是64位整数.于是我小小改动一点使得解析出来数的时候同一时候保留原始的number literal. [使用double表示int的话一般而言53位整数内是OK的.大概算法是在IEEE754中双精度浮点数去掉符号1位和指数11位为64-1-11=52的尾数.2的52次方是4503599627370496,简记为4.5*10^15. 參考:http://zh.wikipedia.org/zh-cn/IEEE_754
和 http://bolt.xunlei.com/faq.html ]
3.须要注意json在array最后一个元素后的逗号的处理;
4.json串本身是什么编码,库在解析使uxxxx的形式的字符的时候是不是OK.(记得在jsoncpp中出过问题,后来使用了chromium里base里的Value.假设不是提前和server端和其他端讨论这个问题,说不定又被坑了.这是在动摇信念后的事了).
可是这些坑都无法动摇我对json的信念,直到有一天,我导师给了我一个1685366字节的json数据我用simple json解析的时候花了十几秒(笔记本上),使得在下面的几年内对json无法直视.每当别人使用json的时候我会说:哥有个不到2M的json数据,能让你的解析速度非常慢,十几秒喔. 每每遇到须要处理格式化的内容时,我就转向了xml的怀抱,而相对熟悉的是rapidxml.可是rapidxml也有坑啊:
1.rapidxml在原有文档上改动. 所以在解析前最好是拷贝一份输入.
2.格式化的时候,非常多都是指针操作,你不能暂时new一个出来,或者指向暂时的变量.而要专门开辟一个存储区域,须要的时候在里面放字符串,格式化完毕后再统一回收.
3.格式化的时候最好用sstream,否则速度会慢点.
4.须要捕获异常.
5.最好仅仅处理utf8的串. 假设是utf16,在结点属性,或者文本结点上放个中文"一",试试,立即就异常了.
直到后来,我更懒了,更喜欢http的header的格式.一个key加一个":",后面跟value.不同的kv用"\r\n"切割.非常快就能写一个解析这种数据的代码.
--------------------------------------------------------------------------
直到昨天,也是老罗和自如大战后的第N天,我想:我也来測评一下那几个json库吧.參战的是:SimpleJSON,jsoncpp,libjson,rapidjson. 挑战目标是那个传说中的1685366字节的json文件. 仅仅作文件解析.
几个库都还大,共同点是:如今都喜欢移到github上了. 比方SimpleJSON迁到github上的时候我仅仅有download下来master上的代码. 其老巢mjpa.co.uk一打开就是File not found.只是后来对照了一下代码,目測master上的代码能够直接当release的使用. 几个开发人员在软件维护性上的黑魔法[參考:http://blog.jobbole.com/76216/]比較少,还算比較人道,非常easy就编译出来了.当中略微黑一点的是libjson,须要自己去关一下C接口.调试版本号须要开一个宏.
jsoncpp是灰色的,须要用scons,可是我没弄成功. 在makefiles下找到了vsproject,升级一下就能用.
人懒,写的測试代码仅仅是勉强能用.大概是一个函数读了个文件,把utf8和utf16输出到两个全局变量里. 定义了个:
void simple_json_test(const char* utf8, const wchar_t* utf16);
void rapid_json_test(const char* utf8, const wchar_t* utf16);
void json_cpp_test(const char* utf8, const wchar_t* utf16);
void lib_json_test(const char* utf8, const wchar_t* utf16);
在主函数里调用这些函数. 用clock()函数计时. 每次换一个函数,又一次编译后就有结果.详细測试函数体加起来11行, 有些代码连资源释放也懒得写了.
SimpleJSON:56,62,57
rapidjson:16,16,15
jsoncpp:60,45,68
libjson:9,9,16
该结果使得我恢复了对json的信仰,可是不明确SimpleJSON前后差异为什么那么大.找出曾经的SimpleJSON的库,又一次跑了一次结果是:
SimpleJSON_old:6893,6826,6844
vs的性能分析没细致看,简单的代码review后发现改变并不大,可是终于还是被我发现猫腻所在.
在JSON.h中有个函数:
// Simple function to check a string 's' has at least 'n' characters
static inline bool simplejson_wcsnlen(const wchar_t *s, size_t n) {
if (s == 0)
return false; const wchar_t *save = s;
while (n-- > 0)
{
if (*(save++) == 0) return false;
} return true;
}
在JSON.cpp中181行,JSONValue.cpp中62,70行被引用,而老版本号中的相应代码是:
// We need 5 chars (4 hex + the 'u') or its not valid
if (wcslen(*data) < 5) // Is it a boolean?
else if ((wcslen(*data) >= 4 && wcsncasecmp(*data, L"true", 4) == 0) || (wcslen(*data) >= 5 && wcsncasecmp(*data, L"false", 5) == 0)) // Is it a null?
else if (wcslen(*data) >= 4 && wcsncasecmp(*data, L"null", 4) == 0)
假设将老版本号的这三处换为新版本号的则问题解决. 当然,替换前后对照,问题是什么也非常明显.
对json的爱恨情仇的更多相关文章
- Menu与ActionBar的爱恨情仇
最近在开发一款音乐播放器,在开发过程中遇到了一点小麻烦,通过android API搞清楚了Menu与ActionBar的爱恨情仇,写了个小Demo祭奠一下那些年我们陷进去的坑,有不对的地方请大神们批评 ...
- web移动端fixed布局和input等表单的爱恨情仇 - 终极BUG,完美解决
[问题]移动端开发,ios下当fixed属性和输入框input(这里不限于input,只要可以调用移动端输入法的都包括,如:textarea.HTML5中contenteditable等),同时存在的 ...
- 注解:大话AOP与Android的爱恨情仇
转载:大话AOP与Android的爱恨情仇 1. AOP与OOP的区别 平时我接触多的就是OOP(Object Oriented Programming面向对象).AOP(Aspect Oriente ...
- 除了love和hate,还能怎么表达那些年的“爱恨情仇”?
实用英语 帮你全面提高英语水平 关注 童鞋们每次刷美剧的时候,相信都会被CP感满满的男女主角虐得体无完肤吧. 可是,一到我们自己表达爱意或者恨意的时候,却苦于词穷,只会用love, like, hat ...
- String、StringBuilder、StringBuffer的爱恨情仇
第三阶段 JAVA常见对象的学习 StringBuffer和StringBuilder类 (一) StringBuffer类的概述 (1) 基本概述 下文以StringBuffer为例 前面我们用字符 ...
- [转帖]探秘华为(一):华为和H3C(华三)的爱恨情仇史!
探秘华为(一):华为和H3C(华三)的爱恨情仇史! https://baijiahao.baidu.com/s?id=1620703498823290828&wfr=spider&fo ...
- Tidyverse|数据列的分分合合,爱恨情仇
Tidyverse|数据列的分分合合,爱恨情仇 本文首发于“生信补给站”Tidyverse|数据列的分分合合,一分多,多合一 TCGA数据挖掘可做很多分析,前期数据“清洗”费时费力但很需要. 比如基因 ...
- pytorch和tensorflow的爱恨情仇之基本数据类型
自己一直以来都是使用的pytorch,最近打算好好的看下tensorflow,新开一个系列:pytorch和tensorflow的爱恨情仇(相爱相杀...) 无论学习什么框架或者是什么编程语言,最基础 ...
- pytorch和tensorflow的爱恨情仇之定义可训练的参数
pytorch和tensorflow的爱恨情仇之基本数据类型 pytorch和tensorflow的爱恨情仇之张量 pytorch版本:1.6.0 tensorflow版本:1.15.0 之前我们就已 ...
随机推荐
- 09C++指针
指针 6.1 指针的概念 请务必弄清楚一个内存单元的地址与内存单元的内容这两个概念的区别.在程序中一般是通过变量名来对内存单元进行存取操作的.其实程序经过编译以后已经将变量名转换为变量的地址,对变量值 ...
- 第2节 mapreduce深入学习:7、MapReduce的规约过程combiner
第2节 mapreduce深入学习:7.MapReduce的规约过程combiner 每一个 map 都可能会产生大量的本地输出,Combiner 的作用就是对 map 端的输出先做一次合并,以减少在 ...
- 18mybatis
18mybatis-2018/08/02 1.mybatis标签 定义SQL语句 id :唯一的标识符 parameterType:传给此语句的参数的全路径名或别名例:com.test.poso.Us ...
- 51nod 1057 n的阶乘 (压位优化)
题目地址:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1057&judgeId=605203 使用压位进行优化, ...
- Python飞机大战实例有感——pygame如何实现“切歌”以及多曲重奏?
目录 pygame如何实现"切歌"以及多曲重奏? 一.pygame实现切歌 初始化路径 尝试一 尝试二 尝试三 成功 总结 二.如何在python多线程顺序执行的情况下实现音乐和音 ...
- 树莓派2-SSH
树莓派3系统SSH是默认关闭的, 将SD卡插入linux, 在root 分区, 修改/etc/rc.local 在exit 0前增加一行 /ect/init.d/ssh start 将SD卡插回树莓派 ...
- mycat——未完成
https://www.cnblogs.com/joylee/p/7513038.html https://blog.csdn.net/wrs120/article/details/80417345 ...
- AutoEncoders原理
目录 Auto-Encoders How to Train? Auto-Encoders How to Train?
- gcc 编译多个源文件
序 Linux 内核和许多其他自由软件以及开放源码应用程序都是用 C 语言编写并使用 GCC 编译的. 编译C++程序 编译.链接命令 -c 只编译不里链接 -o链接 例: g++ file1 -c ...
- 【XML】-- C#读取XML中元素和属性的值
Xml是扩展标记语言的简写,是一种开发的文本格式. 啰嗦几句儿:老师布置的一个小作业却让我的脑细胞死了一堆,难的不是代码,是n多嵌套的if.foreach,做完这个,我使劲儿想:我一女孩,没有更多女孩 ...