jsoncpp初探

1.jsoncpp简介

首先说一下JSON。JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。它基于ECMAScript的一个子集。 JSON采用完全独立于语言的文本格式,这些特性使JSON成为理想的数据交换语言,易于人阅读和编写,同时也易于机器解析和生成,一般用于网络传输。

jsoncpp就是用于生成和解析json的C++开源代码库。 官网见:here,源代码托管在github:here

除了jsoncpp,可供我们选择的第三方开源的用于解析和生成json的C++库还有很多。比如SimpleJSONjson-spirit腾讯的RapidJSON,当然还有C语言的cJSONlibJSON。这里之所以介绍jsoncpp是因为我周边的人用的比较多,相比腾讯的RapidJSON,本来是想用RapidJSON,但是到github上一看,被那纷杂的头文件给吓到了,虽然jsoncpp的头文件也很多,但是相对来说还是少很多。还有一点,jsoncpp用的人多,网上解决问题的资源也就相对多一点。

这里贴一张RapidJSON的作者Milo Yip对网上开源的json库的测评图,测试环境Corei5-3330S@2.70GHz_mac64_clang6.1_1

解析json字符串的时间:

具体参见github Milo Yip native-json benchmark

1.1jsoncpp的内容

(1)JsonCpp主要包含三种类型:Value、Reader和Writer;

Json::Value是jsoncpp 中最基本、最重要的类,用于表示各种类型的对象,jsoncpp 支持的对象类型可见 Json::ValueType 枚举值。

Json::Reader是用于读取的,说的确切点,是用于将字符串转换为 Json::Value 对象的。

Json::Writer类是一个纯虚类,并不能直接使用。在此我们使用 Json::Writer 的子类:Json::FastWriter、Json::StyledWrite、Json::StyledStreamWriter。

(2)Jsoncpp中所有对象、类名都在namespace json中,包含json.h即可

2.jsoncpp下载与编译

第一步:请到github上下载jsoncpp源码,点击这里

github上托管的是jsoncpp整个项目,包括了很多乱七八糟的文件,比如说明文件README.md,示例代码,构建文件cmake.txt,还有各种乱起八糟的脚本文件,不得不吐槽一下,真的很乱。我们需要的仅仅只是其源码,在说明文件中还没有显明的指出源码的所在目录,这点做的不好啊,看了很多其它的开源项目,不仅仅是jsoncpp没有说明,很多都没有说明。还要自己去摸索,筛选自己真真需要的那几个源码文件,真的很令人头痛。

好了,我们需要的源码文件有目录/include/json/ 下的所有头文件,还有目录/src/lib_json/ 下的源文件。这里我又要吐槽一下(可能我有简洁强迫症),源文件目录下还放scon脚本做甚,更有甚者,还放了个头文件json_tool.h。作者对项目文件的组织管理能力我真不敢恭维啊!要是我,源文件目录绝对只放源文件,还参杂其它的文件做咩。

源文件目录/src/lib_json/ 不需要要的文件见下图的红框,请把它删掉吧,碍眼!

其中CMakeLists.txt是CMake用于构建项目的脚本,sconscript是scons构建项目的脚本,version.h.in是github自动生成的版本信息。删删删,统统删了,用不到。当然你如果使用cmake来构建项目的话, CMakeLists.txt还是有用的。Linux下,我是不用cmake,虽然它简单好用,但是在每个目录下都要加个CMakeLists.txt,真的很碍眼(个人感觉)。而且CMake最终也是要生成makefile来构建项目,为何不手写一个makefile全部搞定。

第二步: 编译。将上面说明的我们需要的源文件和头文件包含到自己的项目中就可以使用啦。当然你也可以单独将jsoncpp编译成静态链接库或者动态链接库来使用。这里贴一下我用于编译的makefile,喜欢手写makefile的朋友可以通通交流。

##################################
# @brief:make scripts
# @date:2016.06.25
# @author:dablelv
##################################

#environment var
VPATH+=src:src/lib_json

CC:=g++
FLAGS=-g -Wall -std=c++11
INC+=-Iinc
LIBDIR+=

CPPDIRS=src src/lib_json

TARGET:=jsoncpptest.out

CPPS=$(shell for dir in ${CPPDIRS};do echo $${dir}/*.cpp;done)

OBJDIR=obj
OBJS=$(patsubst %.cpp,${OBJDIR}/%.o,$(notdir ${CPPS}))

${TARGET}:${OBJS}
    ${CC} ${FLAGS} ${OBJS} -o $@ ${LIBDIR}

${OBJDIR}/%.o:%.cpp
    ${CC} ${FLAGS} ${INC} -o $@ -c $<

.PHONY:clean
clean:
    rm -f ${TARGET} ${OBJDIR}/*

3.jsoncpp使用实例

下面直接上代码。

#include <string.h>

#include <string>
#include <iostream>
using namespace std;

#include "json/json.h"

struct Student{
    char ID[20];
    char name[10];
    int age;
    int gender;
    char major[10]; 
};

string serializeToJson(const Student& student);
Student deserializeToObj(const string& strJson);

int main(int argc, char** argv) {

    Student student;
    strcpy(student.ID,"312822199204085698");
    strcpy(student.name,"dablelv");
    student.age=18;
    student.gender=0;
    strcpy(student.major,"math");

    string strJson=serializeToJson(student);
    cout<<"strJson:"<<strJson<<endl;

    string strJsonNew="{\"ID\":\"201421031059\",\"name\":\"lvlv\",\"age\":18,\"gender\":0}";
    Student resStudent=deserializeToObj(strJsonNew);
    cout<<"resStudent:"<<endl;
    cout<<"ID:"<<resStudent.ID<<endl;
    cout<<"name:"<<resStudent.name<<endl;
    cout<<"age:"<<resStudent.age<<endl;
    cout<<"gender:"<<resStudent.gender<<endl;
    cout<<"major:"<<resStudent.major<<endl;

    return 0;
}

//@brief:将给定的学生对象序列化为json字符串
//@param:student:学生对象
//@ret:json字符串
string serializeToJson(const Student& student){
    //Json::Value root;
    Json::FastWriter writer;
    Json::Value person;

    person["ID"] = student.ID;
    person["name"] = student.name;
    person["age"]=student.age;
    person["gender"]=student.gender;
    person["major"]=student.major;
    //root.append(person);

    string strJson=writer.write(root);
    return strJson;
}

//@brief:将给定的json字符串反序列化为学生对象
//@param:strJson:json字符串
//@ret:学生对象
Student deserializeToObj(const string& strJson){
    Json::Reader reader;
    Json::Value value;
    Student student;
    memset(&student,0,sizeof(Student));

    if (reader.parse(strJson, value)){
        strcpy(student.ID,value["ID"].asString().c_str());
        strcpy(student.name,value["name"].asString().c_str()); 
        student.age=value["age"].asInt(); 
        student.gender=value["gender"].asInt();
        strcpy(student.major,value["major"].asString().c_str());
    }
    return student;
}

程序输出结果:

上面的major输出之所以为空,是因为json字符串中没有major字段。


参考文献

[1]jsoncpp官网 [2]jsoncpp github [3]native-json benchmark [4]C++ Jsoncpp源代码编译与解析Json

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏osc同步分享-java技术分享站

在springBoot项目中使用activiti

http://www.jvm123.com/2019/08/springboot-activiti/

3.8K70
来自专栏禁心尽力

实战技能:小小微信支付业务,何必虚惊一场

记得上次接触微信支付是2016年底,那次也是我程序生涯中首次碰及支付业务,慌张谈不上但是懵逼怀疑时时都有。说起第三方登录或者支付,想必都清楚是直接调用人家现成的...

13720
来自专栏Hongten

JSP 六讲

15720
来自专栏ShaoYL

XCode调试器LLDB

16760
来自专栏.NET后端开发

深入理解DIP、IoC、DI以及IoC容器

摘要 面向对象设计(OOD)有助于我们开发出高性能、易扩展以及易复用的程序。其中,OOD有一个重要的思想那就是依赖倒置原则(DIP),并由此引申出IoC、DI以...

34680
来自专栏菩提树下的杨过

velocity模板引擎学习(1)

velocity与freemaker、jstl并称为java web开发三大标签技术,而且velocity在codeplex上还有.net的移植版本NVeloc...

22450
来自专栏王清培的专栏

.NET框架设计(高级框架架构模式)—钝化程序、逻辑冻结、冻结程序的延续、瞬间转移

阅读目录: 1.开篇介绍 2.程序书签(代码书签机制) 2.1ProgramBookmark 实现(使用委托来锚点代码书签) 2.2ProgramBookma...

228100
来自专栏BaronTalk

在Android项目中使用Java8

前言 在过去的文章中我介绍过Java8的一些新特性,包括: Java8新特性第1章(Lambda表达式) Java8新特性第2章(接口默认方法) Java8新特...

32260
来自专栏华章科技

Ruby 和 Python 分析器是如何工作的?

你好! 我作为一名编写Ruby profiler的先驱,我想对现有的Ruby和Python profiler如何工作进行一次调查。 这也有助于回答很多人的问题:...

12120
来自专栏互扯程序

Java 9 逆天的十大新特性

KS Knowledge Sharing 知识分享 现在是资源共享的时代,同样也是知识分享的时代,如果你觉得本文能学到知识,请把知识与别人分享。 在介绍...

27260

扫码关注云+社区

领取腾讯云代金券