JsonCpp 入门教程_恋喵大鲤鱼的博客-程序员宅基地

技术标签: 开源源码分析与使用  

1.JsonCpp 简介

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

JsonCpp 是用于生成和解析 JSON 的 C++ 开源库,参见官网,源代码托管在Github

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

这里贴一张 RapidJSON 的作者 Milo Yip 对网上开源的 JSON 库的测评图,测试环境[email protected]_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/下的源文件。这里我又要吐槽一下(可能我有简洁强迫症),源文件目录下还放脚本 sconscript 做甚,更有甚者,还放了个头文件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

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/K346K346/article/details/51758578

智能推荐

csnd ftp服务器端java,HTTP协议之分块传输与分段编码-程序员宅基地

目录数据的分块传输我们都知道http协议是由TCP协议封装而来的应用层协议。我们和服务器之间的每次http交互都要进行三次握手和四次挥手。那么,服务器端怎么判断客户端传来的数据已经发送完了,然后断开这次tcp连接呢?我们客户端在发送给服务器端报文中有一个Connection字段,一般这个值为close。也就是说这次数据传输完成了,服务器就会断开这次tcp连接。但是,当我们要传送的数据量比较大时,一..._分段直接编码是什么

论文阅读 L2M-GAN:《L2M-GAN: Learning to Manipulate Latent Space Semantics for Facial Attribute Editing》-程序员宅基地

论文地址:来源:CVPR 2021文章目录1. 背景知识2. 具体算法2.1 算法流程2.2 损失函数2.3 应用3. 实验3.1 定性实验3.2 定量实验3.3 消融实验3.4 其他属性操作任务的结果总结1. 背景知识深度人脸属性编辑模型力求满足两个要求:(1)属性正确性——目标属性应该正确出现在编辑后的人脸图像上; (2) 不相关保存——任何不相关的信息(如身份)在编辑后不应更改。现有方法一:基于空间注意力假设是每个属性都有局部支持区域,可以使用编码器-解码器 GAN 框架的特征图上的.

STM32自学笔记 第六篇,时钟TIM 3之MAX6675测温5_stm32 max6775-程序员宅基地

说说程序下文中参数j为16位整数void GPIO_Configuration(void){GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;GPIO_InitStructure.GPIO_Pin=GPIO_Pin_4;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(..._stm32 max6775

i.e./e.g./etc.如何发音_id est拉丁语怎么读-程序员宅基地

i.e./e.g./etc.如何发音_id est拉丁语怎么读

pydoc是什么?-程序员宅基地

python中pydoc模块可以从python代码中获取docstring,然后生成帮助信息。windows环境下,命令行运行:python -m pydoc atexitLinux环境下直接运行:pydoc atexitHTML帮助pydoc还能够生成HTML输出,既可以将HTML帮助信息输出到静态文本中,也可以启动一个Web服务器在线浏览帮助文档。Windo...

钉钉回调 base64 解密报错_base64.decodebase64 last encoded character is a va-程序员宅基地

钉钉回调一直报错java.lang.IllegalArgumentException: Last encoded character (before the paddings if any) is a valid base 64 alphabet but not a possible value. Expected the discarded bits to be zero. at org.apache.commons.codec.binary.Base64.validateCharacte..._base64.decodebase64 last encoded character is a valid base 64 alphabat but n

随便推点

并发模拟工具(JMeter、Apache Bench、postMan)详解-程序员宅基地

目录简介: 一、Psotman:Http请求模拟工具 1.1 下载地址 1.2 操作说明(以win64为例) 二、Apace Bench(AB):Apache附带的工具,测试网站性能 2.1 简介 2.2 原理 2.3 Apache Bench安装 2.4 Apache Bench 使用 2.5 使用注意 三、JMeter:Apache组织开发的压力测试工具(使用比较多的工具)

苹果手机几月份最便宜_最便宜的苹果快充数据线:ZMI USB-C to Lightning数据线评测...-程序员宅基地

本文作者:善生的善生萨瓦迪卡,我是善生。USB-C to Lightning线,主要用于iPhone和iPad的快充。随着各家陆续走完了MFI的流程,以及C94端子的供货上量,越来越多第三方线材开始出货了。横评自然是少不了的,来先给你们看一下我屯的货,目前开售的基本都买回来了。数据测试还在做,大家可以期待一下。大妈首发,全网独一份。最近有很多同学给我留言,问ZMI这根线怎么样。在横评出来之前,我会...

Django 的模板中的数学运算-程序员宅基地

为什么80%的码农都做不了架构师?>>> ..._django withratio是怎么运行的

CEGUI显示中文的一些细节-程序员宅基地

在CEGUI中配置中文字体已经没什么困难, 为CEGUI的一个文本赋值,必须是uft8类型的字符串, 想使用std::string作为输入参数,就必须进行相应的转换, std::wstring s2ws(const std::string& s){ std::string curLocale = setlocale(LC_ALL, NULL); // curLocale = "C"; setlocale(LC_A

Java从零开始实现导出excel(二)_aftersheetcreate_追晨始梦的博客-程序员宅基地

Java从零开始实现导出excel(二)新人博主,随笔记录。主要还是通过自己日常工作积累,系统整理一些技术。希望能够节省更多人的时间,走出自己的路。看了自己发的文章,可以帮助一些小伙伴很开心!!简述:上一篇文章主要用我个人觉得,效果很好的方法做excel的导出。但是那只是符合正常,简单的excel导出。可能很多小伙伴,会遇到一些复杂的样式的excel的导出。这一篇同样是用EasyExcel,主要是做一些数据格式复杂的excel,当然这一篇文章不包含复杂表头的excel导出环境搭建:这一篇的环境和_aftersheetcreate

简看线程池原理-程序员宅基地

“池”技术对我们来说是非常熟悉的一个概念,它的引入是为了在某些场景下提高系统某些关键节点性能,最典型的例子就是数据库连接池,JDBC是一种服务供应接口(S...