基于开源库jsoncpp的json字符串解析

小小鸟儿!      2022-02-14     683

关键词:

json(JavaScript Object Notation)是一种轻量级高效数据交换格式。相比于XML,其更加简洁,解析更加方便。在实习期间,我负责的程序模块,多次使用到json进行数据传输。由于之前只对json稍稍了解,而且不熟悉项目组使用的开源json解析库,故在编码过程中效率很低,而且还出现过bug。虽然,最后项目组的事情比较顺利的完成了,但感觉自己对json的编解码熟悉仍然不够,故翻阅了相关文档,写下这篇技术博客。与君共勉。

1.什么是json

    JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。它基于ECMAScript的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C、C++、C#、Java、JavaScript、Perl、Python等)。这些特性使JSON成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成(网络传输速率)[摘自百度百科]。

    再举个简单的例子。假如要用xml和json来存储一个学生的个人信息,则XML和json的数据格式分别如下:

XML:

<student>

    <name>joekuang</name>

    <age>25</age>

   <hobby>sports</hobby>

</student>

json:

{"name":"joekuang","age":25,"hobby":"sports"}

    相比之下,显而易见,json存储所需的空间要小得多,数据更加简洁。不过xml也有它的好处,就是格式清晰明了,更容易解析。

2.jsoncpp简介及测试用例

   jsoncpp是一个开源的轻量级C++ json解析库,简单易用,非常方便。可通过如下两个地址获取源码:(1)http://sourceforge.net/projects/jsoncpp/  (2) https://github.com/open-source-parsers/jsoncpp。json源码的目录如下:

[html] view plain copy
  1. ├── include  
  2. │   └── json  
  3. │       ├── autolink.h  
  4. │       ├── config.h  
  5. │       ├── features.h  
  6. │       ├── forwards.h  
  7. │       ├── json.h  
  8. │       ├── reader.h  
  9. │       ├── value.h  
  10. │       └── writer.h  
  11. ├── makefile  
  12. └── src  
  13.     ├── json  
  14.     │   ├── json_batchallocator.h  
  15.     │   ├── json_internalarray.inl  
  16.     │   ├── json_internalmap.inl  
  17.     │   ├── json_reader.cpp  
  18.     │   ├── json_value.cpp  
  19.     │   ├── json_valueiterator.inl  
  20.     │   ├── json_writer.cpp  
  21.     │   └── sconscript  
  22.     └── main.cpp  
如上图所示,include/json目录下为开源解析库头文件目录,src/json为源码文件,main.cpp为测试用例文件。通过在根目录下键入make命令,即可生成可执行程序main,运行就能看到例子效果。测试用例源码如下:

  1. #include <string>  
  2. #include <json/json.h>  
  3.   
  4. void readJson();  
  5. void writeJson();  
  6.   
  7. int main(int argc, char** argv) {  
  8.     readJson();  
  9.     writeJson();  
  10.     return 0;  
  11. }  
  12.   
  13. void readJson() {  
  14.     using namespace std;  
  15.     std::string strValue = "{"name":"json","array":[{"cpp":"jsoncpp"},{"java":"jsoninjava"},{"php":"support"}]}";  
  16.   
  17.     Json::Reader reader;  
  18.     Json::Value value;  
  19.   
  20.     if (reader.parse(strValue, value))  
  21.     {  
  22.         std::string out = value["name"].asString();  
  23.         std::cout << out << std::endl;  
  24.         const Json::Value arrayObj = value["array"];  
  25.         for (unsigned int i = 0; i < arrayObj.size(); i++)  
  26.         {  
  27.             if (!arrayObj[i].isMember("cpp"))   
  28.                 continue;  
  29.             out = arrayObj[i]["cpp"].asString();  
  30.             std::cout << out;  
  31.             if (i != (arrayObj.size() - 1))  
  32.                 std::cout << std::endl;  
  33.         }  
  34.     }  
  35. }  
  36.   
  37. void writeJson() {  
  38.     using namespace std;  
  39.   
  40.     Json::Value root;  
  41.     Json::Value arrayObj;  
  42.     Json::Value item;  
  43.   
  44.     item["cpp"] = "jsoncpp";  
  45.     item["java"] = "jsoninjava";  
  46.     item["php"] = "support";  
  47.     arrayObj.append(item);  
  48.   
  49.     root["name"] = "json";  
  50.     root["array"] = arrayObj;  
  51.   
  52.     root.toStyledString();  
  53.     std::string out = root.toStyledString();  
  54.     std::cout << out << std::endl;  
  55. }  
  56. </span>  

执行效果如下:

技术分享

技术分享
在实际使用开源库的过程中,为了方便起见,我一般把include和src两个目录下的文件进行合并。

技术分享

3.如何使用jsoncpp

   对于绝大部分程序员来说,只要了解jsoncpp中的三个类的使用就基本可以完成json数据的生成与解析工作。这三个类分别是:Json::Value,Json::Reader,Json::Writer。

3.1 Json::Value

   Json::Value jsoncpp 中最基本、最重要的类,用于表示各种类型的对象,jsoncpp 支持的对象类型可在value.h文件的ValueType中查看,包括:

1.nullValue空值类型,即内容为空
2.intValue 有符号整型类型      
3.uintValue 无符号整型
4.realValue 有理数,即浮点数
5.stringValue 字符串
6.booleanValue 布尔类型:true,false
7.arrayValue 数组,数组内容可为上述6种
8.objectValue 对象类型,对象内容可为上述7种

现在就基于上述几种类型构建一个复杂的Json::Value。

  1. Json::Value joe;  
  2. joe["name"]=Json::Value("joekuang");  
  3. joe["age"]=Json::Value(25);  
  4. joe["wage"]=Json::Value(123.45);  
  5. joe["wife"]=Json::Value();  
  6. joe["hobby"].append("running");  
  7. joe["hobby"].append("basketball");  
  8. Json::Value family;  
  9. family["name"]=Json::Value("joe‘s home");  
  10. family["isCountry"]=Json::Value(true);  
  11. family["member"]=joe;  


3.2 Json::Writer

    在3.1节中,产生的Json数据,要怎么才能显示出来呢?或者说,怎么转换成可查看的内容(string)?这个时候,就需要使用到Json::Writer了。Json::Writer是一个虚类,不能直接使用,我们可以通过它的两个子类Json::FastWriter和Json::StyledWriter来输出显示。两者的区别是,FastWriter显示的内容去掉了格式(回车等),为纯字符串,而StyledWriter保留了格式。现在我们通过实例,来将3.1中生成的Json数据打印出来。

  1. Json::FastWriter fast_writer;  
  2. Json::StyledWriter styled_writer;  
  3. std::cout << fast_writer.write(family)<< std::endl;  
  4. std::cout << styled_writer.write(family)<< std::endl;  

输出结果为:

技术分享

技术分享

3.3 Json::Reader

    Json::Reader的作用是将字符串解析为Json::Value对象,解析使用Reader对象的parse函数。我们直接提取3.2生成的字符串来做解析,完整源码见附录。

  1. std::string  sFamilyJson="{"isCountry":true,"member":{"age":25,"hobby":["running","basketball"],"name":"joekuang","wage":123.450,"wife":null},"name":"joe‘s home"}";  
  2. Json::Value family;  
  3. Json::Reader reader;  
  4. if(!reader.parse(sFamilyJson,family))  
  5. {  
  6. <span style="white-space:pre">    </span>std::cout<<"parse string to json failed !"<<std::endl;  
  7. <span style="white-space:pre">    </span>return -1;  
  8. }  
  9. int iAge=family["member"]["age"].asInt();  
  10. double dWage=family["member"]["wage"].asDouble();  
  11. std::string sFamily=family["name"].asString();  
  12. std::string sSecondHobby=family["member"]["hobby"][1].asString();   
  13.   
  14.   
  15. std::cout << "joe‘s age  is:"<< iAge<< std::endl;  
  16.   std::cout << "joe‘s wage is:"<<dWage<< std::endl;  
  17. std::cout << "family name is:"<< sFamily<< std::endl;  
  18.   std::cout << "joe‘s second hobby is:"<<sSecondHobby<< std::endl;  
  19. return 0;  
  20. }  

解析结果为:

技术分享

技术分享

4.注意事项

    通过上文,基本可以完成简单的json生成与解析了。但还有些小问题需要注意。

4.1 异常抛出

    在解析的过程中,可能会有异常抛出,比如对Json::Value的下标取值操作,如果数据为非ArrayValue,则会抛出异常。故,建议编码的过程中,加入TryCatch来做异常捕获。

4.2 区分字符串与Json数据

    比如以下两个Json字符串,是不能用同样方式解析的。

  1. {"isCountry":true,"member":{"age":25,"hobby":["running","basketball"],"name":"joekuang","wage":123.450,"wife":null},"name":"joe‘s home"}  
  1. {"isCountry":true,"member":{"age":25,"hobby":"["running","basketball"]","name":"joekuang","wage":123.450,"wife":null},"name":"joe‘s home"}  

在hobby这个key对应的数据中,第一个对应的为ArrayValue,第二个对应的是stringValue。对于第一个,我们直接用[]操作就可以把Hobby对应的数据取出来了。而对于第二个,实际上我们需要使用reader进行第二次解析,把字符串解析为ArrayValue。

4.3其它注意事项

    暂时没有,后续有机会再补充。

附录:

1.Json::Writer例子完整源码:

  1. #include <string>  
  2. #include <json/json.h>  
  3.   
  4.   
  5. int main(int argc, char** argv) {  
  6.     Json::Value joe;  
  7.     joe["name"]=Json::Value("joekuang");  
  8.     joe["age"]=Json::Value(25);  
  9.     joe["wage"]=Json::Value(123.45);  
  10.     joe["wife"]=Json::Value();  
  11.     joe["hobby"].append("running");  
  12.     joe["hobby"].append("basketball");  
  13.     Json::Value family;  
  14.     family["name"]=Json::Value("joe‘s home");  
  15.     family["isCountry"]=Json::Value(true);  
  16.     family["member"]=joe;     
  17.     Json::FastWriter fast_writer;  
  18.     Json::StyledWriter styled_writer;  
  19.     std::cout << fast_writer.write(family)<< std::endl;  
  20.     std::cout << styled_writer.write(family)<< std::endl;  
  21.     return 0;  
  22. }  

2.Json::Reader例子完整源码:

  1. #include <string>  
  2. #include <json/json.h>  
  3.   
  4.   
  5. int main(int argc, char** argv) {  
  6. std::string  sFamilyJson="{"isCountry":true,"member":{"age":25,"hobby":["running","basketball"],"name":"joekuang","wage":123.450,"wife":null},"name":"joe‘s home"}";  
  7. Json::Value family;  
  8. Json::Reader reader;  
  9. if(!reader.parse(sFamilyJson,family))  
  10. {  
  11. std::cout<<"parse string to json failed !"<<std::endl;  
  12. return -1;  
  13. }  
  14. int iAge=family["member"]["age"].asInt();  
  15. double dWage=family["member"]["wage"].asDouble();  
  16. std::string sFamily=family["name"].asString();  
  17. std::string sSecondHobby=family["member"]["hobby"][1].asString();   
  18.   
  19.   
  20.   
  21.   
  22. std::cout << "joe‘s age  is:"<< iAge<< std::endl;  
  23.   std::cout << "joe‘s wage is:"<<dWage<< std::endl;  
  24. std::cout << "family name is:"<< sFamily<< std::endl;  
  25.   std::cout << "joe‘s second hobby is:"<<sSecondHobby<< std::endl;  
  26. return 0;  
  27. }  

3.整理后的开源库文件

http://pan.baidu.com/s/1qWGatzQ


转载地址:http://blog.csdn.net/kxc0720/article/details/48422595





















jsoncpp的使用

开源代码地址github:https://github.com/open-source-parsers/jsoncpp使用的时候直接包含.h和.cpp到项目中,也可以编译成lib库来使用。json简单字符串解析:1//简单Json2voidConfig1()3{4Json::Valueroot;5Json::Readerreader;6std::stringstr="{"ip":"127.0 查看详情

c++解析json——jsoncpp

Jsoncpp是个跨平台的开源库,下载地址:http://sourceforge.net/projects/jsoncpp/,我下载的是v0.5.0,压缩包大约104K。方法一:使用Jsoncpp生成的lib文件     解压上面下载的Jsoncpp文件,在jsoncpp-src-0.5.0/makefiles/vs71目录里找... 查看详情

c++的json解析库:jsoncpp和boost(转)

原文转自http://blog.csdn.net/hzyong_c/article/details/7163589 JSON(JavaScriptObjectNotation)跟xml一样也是一种数据交换格式,了解json请参考其官网http://json.org,本文不再对json做介绍,将重点介绍c++的json解析库的使用方法。json官网上列出了各... 查看详情

在c++环境中使用jsoncpp读写json数据

...一种轻量级的数据交换格式。通常用于数据交换或存储。JsonCpp是一个基于C++语言的开源库,用于C++程序的Json数据的读写操作。 JsonCpp是一个开源库下载地址:https://github.com/open-source-parsers/jsoncpp文档地址:http://open-source-p 查看详情

jsoncpp使用小结(代码片段)

...ncpp介绍    jsoncpp是一个开源C++库,提供对JSON字符串序列化/反序列化的功能。开源地址:https://github.com/open-source-parsers/jsoncpp文档地址:http://open-source-parsers.github.io/jsoncpp-docs/doxygen/index.html 二、jsoncpp的使用  ... 查看详情

jsoncpp使用小结(代码片段)

...ncpp介绍    jsoncpp是一个开源C++库,提供对JSON字符串序列化/反序列化的功能。开源地址:https://github.com/open-source-parsers/jsoncpp文档地址:http://open-source-parsers.github.io/jsoncpp-docs/doxygen/index.html 二、jsoncpp的使用  ... 查看详情

别再推荐使用jsoncpp了(代码片段)

文章目录事件起因为什么不推荐jsoncppjson解析如何优化性能事件起因今天刷视频看到一位大佬写的json解析库的性能超群,秒杀了一众json解析库,其中包括我比较喜欢的nlohmannjson库,这个库在他的测试中性能垫底,... 查看详情

android--开源库fastjson基本使用(代码片段)

...on是阿里巴巴的开源JSON解析库,它可以解析JSON格式的字符串,支持将JavaBean序列化为JSON字符串,也可以从JSON字符串反序列化到JavaBean。优点速度快fastjson相对其他JSON库的特点是快,从2011年fastjson发布1.1.x版本之后&... 查看详情

别再推荐使用jsoncpp了(代码片段)

文章目录事件起因为什么不推荐jsoncppjson解析如何优化性能事件起因今天刷视频看到一位大佬写的json解析库的性能超群,秒杀了一众json解析库,其中包括我比较喜欢的nlohmannjson库,这个库在他的测试中性能垫底,... 查看详情

12.6.2常用的json库

12.6.2常用的Json库1.JsonCpp    JsonCpp是一个C++用来处理JSON数据的开发包。网址:http://jsoncpp.sourceforge.net/2.cJSON    cJSON是一个超轻巧,携带方便,单文件,简单的可以作为ANSI-C标准的JSON解析器。网址:htt... 查看详情

jsoncpp在vs中使用

Jsoncpp是c++生成和解析Json数据的跨平台开源库。下面简介如何在vs中使用。1、官网下载。https://sourceforge.net/projects/jsoncpp/解压文件得到jsoncpp-src-0.5.0文件夹。2、在jsoncpp-src-0.5.0->makefiles->vs71文件夹下找到jsoncpp.sln文件,打开,... 查看详情

jsoncpp使用

...型,如:int,double,string,object,array等Json::Reader:将文件流或字符串创解析到Json::Value中,主要使用parse函数 查看详情

linux(程序设计):31---jsoncpp库(c++操作json)

一、jsoncpp库概述jsoncpp是一个c++封装的json包,跨平台支持windows、linux、unix等多系统jsoncpp源码地址:https://github.com/open-source-parsers/jsoncpp库的安装sudoapt-getinstalllibjsoncpp-dev安装完成之后,头文件默认安装在/usr/include/jsoncpp/json/目录... 查看详情

ios开源json解析库mjextension

...ect互转有两种方式:1、iOS自带类NSJSONSerialization2、第三方开源库SBJSON、JSONKit、MJExtension。项目中一直用MJExtension来进行JSON与Model的互转,非常方便、强大,接下来介绍一下这个轻量、强大的开源库。1、什么是MJExtension?MJExtension... 查看详情

如何在安卓ndk工程中引入jsoncpp

...;:"sunny"",root);Reader可以用来初始化一个人json从字符串。本回答被提问者采纳 查看详情

jsoncpp的使用

Jsoncpp的使用来源 https://www.cnblogs.com/kex1n/archive/2011/12/02/2272328.html JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLanguage, StandardEC 查看详情

c++通过jsoncpp类库读写json文件-json用法详解(代码片段)

...名思义,JSON是用于标记javascript对象的。编译方法:使用Jsoncpp生成的lib文件:首先下载Jsoncpp源码文件,用c 查看详情

sonic:基于jit技术的开源全场景高性能json库(代码片段)

...thub.com/bytedance/sonicsonic是字节跳动开源的一款GolangJSON库,基于即时编译(Just-In-TimeCompilation)与向量化编程(SingleInstructionMultipleData)技术,大幅提升了Go程序的JSON编解码性能。同时结合lazy-load设计思想,它也为不同业务场景打... 查看详情