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,运行就能看到例子效果。测试用例源码如下:

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

[cpp] view plain copy
  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数据打印出来。

[cpp] view plain copy
  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生成的字符串来做解析,完整源码见附录。

[cpp] view plain copy
  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. std::cout << "joe's age  is:"<< iAge<< std::endl;
  14. std::cout << "joe's wage is:"<<dWage<< std::endl;
  15. std::cout << "family name is:"<< sFamily<< std::endl;
  16. std::cout << "joe's second hobby is:"<<sSecondHobby<< std::endl;
  17. return 0;
  18. }

解析结果为:

4.注意事项

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

4.1 异常抛出

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

4.2 区分字符串与Json数据

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

[cpp] view plain copy
  1. {\"isCountry\":true,\"member\":{\"age\":25,\"hobby\":[\"running\",\"basketball\"],\"name\":\"joekuang\",\"wage\":123.450,\"wife\":null},\"name\":\"joe's home\"}
[cpp] view plain copy
  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例子完整源码:

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

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

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

3.整理后的开源库文件

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

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

基于开源库jsoncpp的json字符串解析的更多相关文章

  1. Java基础-处理json字符串解析案例

    Java基础-处理json字符串解析案例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 作为一名开发人员,想必大家或多或少都有接触到XML文件,XML全称为“extensible ...

  2. jsoncpp构造json字符串和json数组

    jsoncpp构造json字符串和json数组 参考文章:Jsoncpp的简单使用 下载json文件夹放在c++项目的include目录下,在CMakeLists中include进去,然后就可以在代码 ...

  3. 前台的js对象数组传到后台处理。在前台把js对象数组转化为json字符串,在后台把json字符串解析为List<>

    前台的js对象数组传到后台处理.在前台把js对象数组转化为json字符串,在后台把json字符串解析为List<>

  4. VBScript把json字符串解析成json对象的2个方法

    这篇文章主要介绍了VBScript把json字符串解析成json对象的2个方法,本文通过MSScriptControl.ScriptControl和jscript实现,需要的朋友可以参考下 asp/v ...

  5. 复杂JSON字符串解析,可以少走弯路

    发现一个好文章:装载至http://www.verejava.com/?id=17174254038220 package com.json5;    import org.json.JSONArra ...

  6. 第三方库 jsoncpp 读写json

    一.摘要 JSON 的全称为:JavaScript Object Notation,顾名思义,JSON 是用于标记 Javascript 对象的,JSON 官方的解释为:JSON 是一种轻量级的数据传 ...

  7. JSON字符串解析成JSON数据格式

    在JS中将JSON的字符串解析成JSON数据格式,一般有两种方式: 1.一种为使用eval()函数. 2. 使用Function对象来进行返回解析. 使用eval函数来解析,并且使用jquery的ea ...

  8. JSON字符串解析

    有时保存在数据库的数据是一串json字符串,需要进行读取的时候就需要解析操作. 简单介绍两种: 1.net.sf.json.* 2.com.alibaba.fastjson.* 需要的包自行下载. 第 ...

  9. Json字符串解析原理、超大json对象的解析

    概述 附上完整的代码:https://pan.baidu.com/s/1dEDmGz3(入口类是Json)JSON:JavaScript 对象表示法(JavaScript Object Notatio ...

随机推荐

  1. Jmeter--正则表达式提取值

    博客首页:http://www.cnblogs.com/fqfanqi/ 设置界面如下: Apply to:应用范围的选择: Field to check:检查的领域,即需要提取内容的地方. 下面是各 ...

  2. AutoArchive settings explained

    AutoArchive settings explained Applies To: Outlook 2010 More... Less AutoArchive helps manage the sp ...

  3. 数据库系统概述(Data Model、DBMS、DBS、RDBS、Structured Query Language)

    数据Data 描述事物的符号记录成为数据. 数据是数据库中存储的基本对象.   除了基本的数字之外.像图书的名称.价格.作者都可以称为数据. 将多种数据记录列成一张表.通过数据表管理数据. 每一行的数 ...

  4. Restful风格到底是什么?怎么应用到我们的项目中?

    rest越来越流行,感觉挺高大尚的.网上看了很多网友的说法,各有各的看法,我觉得很多说得很有道理. 说法一 restful风格,就是一种面向资源服务的API设计方式,它不是规范,不是标准,它一种设计模 ...

  5. tpot从elastic search拉攻击数据之一 找本地数据端口

    前面,我们已经在ubuntu服务器上部署好了tpot,并启动进行数据捕获 可以通过64297端口登陆到kibana可视化平台查看捕获到攻击的情况. 现在要拉取攻击数据了,但是该怎么拉呢? 看了一上午的 ...

  6. django博客项目1.环境搭建

    安装 Python Windows 下安装 Python 非常简单,去 Python 官方网站找到 Python 3 的下载地址,根据你的系统选择 32 位或者 64 位的安装包,下载好后双击安装即可 ...

  7. spring 整合mybatis找不到${jdbc.driverClass}

    1.检查是否设置了mapper扫描org.mybatis.spring.mapper.MapperScannerConfigurer类 在spring里使用org.mybatis.spring.map ...

  8. PHP 安装memcache.so 和memcached.so

    一.memcache.so 的安装 wget http://pecl.php.net/get/memcache-2.2.7.tgztar zxvf memcache-2.2.7.tgz./config ...

  9. python s13 day04

    1.1 all() 和 any( )   all() any()   0,None,"", [], (),{} #布尔值为0的 列举,None ,空列表,空元祖,空. print( ...

  10. django【原生分页】

    1.urls.py url(r'^page2/',views.page2), 2.views.py from django.core.paginator import Paginator,PageNo ...