使用的库
我们使用的库是Jsoncpp
库,是一个面向对象的C++库。
Jsoncpp的使用方法
##使用准备
首先要包含头文件json.h
,然后要使用命名空间Json
。(下面为了清晰我们并没有使用Json命名空间):
|
|
Jsoncpp对文件的结构
Jsoncpp对文件的结构很简单:所有的花括号扩起来的都代表一个Json::Value
,然后里面是键-值对。值可以是任意的基本数据,也可以是Json数组或者另一个Json::Value:
Json文件的写入
Json文件的写入很简单,只要构造Json::Value
就可以了。
由于Json首先就是以一个大括号(Json对象)开始的,所以我们先声明一个Json::Value:
|
|
然后就可以通过类似map的方法添加键值对了:
|
|
这个时候的Json文件如下:
|
|
如果你想要添加另一个json对象也可以:
|
|
这个时候就变为:
|
|
如果想要添加数组的话,只需要使用append()
方法:
|
|
最后结果为:
|
|
如果想要删除,就使用removeMember()
方法。
接下来应该将Json数据写到文件中。这里有两种方法:
- 使用
FastWriter
和StyledWriter
将数据变为字符串,然后通过C++IO来写入文件(这个方法已经废弃,使用的话会给出警告,但是却很方便,所以也列了出来) - 使用
StreamWriterBuilder
和StreamWriter
来将数据变为字符串,然后通过IO写入文件。
也就是说,Jsoncpp本身是不能直接写入文件的,而必须先变为字符串,再通过C++原生IO写入文件。
使用FastWriter
和StyledWriter
这两个类的用法其实是一样的:
|
|
首先声明对象,然后调用write方法传入要变为字符串的Json对象(这里传入root表示整个Json对象)就可以得到字符串了。然后通过C++IO就可以写到文件里面去了:
|
|
结果如下:
|
|
FastWriter
和StyledWriter
的区别在于,FastWriter
是不管格式的,会写的很快(像上面那样)。但是StyledWriter
会通过缩进来控制格式。
使用StreamWriterBuilder
来写入
首先我们需要一个StreamWriterBuilder
对象:
|
|
可以从名称看出,wb是一个“Builder”,也就是说他可以产生写入器。
StreamWriterBuilder
的作用是在写文件之前给出一些配置。配置的话直接通过[配置名称]=配置
就可以了,比如wb["useSpecialFloats"] = true;
这样。有如下配置:
- "commentStyle": "None" or "All"代表注释风格
- "indentation": "
"代表前缀,就是标有'$'的这里: 一般我们也不会去改动这个属性,当然这个属性默认为四个空格。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
{ $$"name" : "VisualGMQ" "age" : 20, "info" : $${ $$$$"school" : "AnHuiLiGongDaXue" $$$$"credit" : "2017303119", $$$$"male" : true, $$}, "friend" : $$[ $$$$"XianFen", $$$$"CaiChuanXun", $$$$"WuTao" $$], }
- "enableYAMLCompatibility": false or true代表是否兼容Yaml,如果为true会在格式上有一些改变
- "dropNullPlaceholders": false or true丢弃null值。
- "useSpecialFloats": false or true如果为true,那么Nan就会记为"NaN",float类型的INFINITY也会被记为"Infinity"
- “precision":小数的精度,默认为17.
你可以用setDefaults()
函数来将设置变为默认的。或者通过validate()
来判断此StreamWriterBuilder的配置是否正确。
配置好之后,你有两种选择来将Json数据变为字符串:
- 直接变为字符串
通过调用
Json::writeString
方法来变为字符串:1
string str = Json::writeString(wb, root);
- 产生写入器,然后通过写入器变成字符串:
这里通过swb的
1 2 3 4 5
Json::StreamWriterBuilder swb; Json::StreamWriter* sw = swb.newStreamWriter(); ofstream ofile("ret1.json"); sw->write(root, &ofile); ofile.close();
newStreamWriter()
创建一个写入器sw,然后通过其(也是仅有的)write
方法写入ofile流中。 写入器的第二个参数是ostream*,也就是说你可以写到文件流中,也可以直接写到输出流中。这里就比第一种方法要 更具有灵活性了。
Json文件的读取
Json文件的读取也有两个方法:使用CharReaderBuilder
,CharReader
或者Reader
来读取。
需要说明的是,Json也不支持直接从文件中解析Json文件。你应该使用C++IO先将文件读到字符串中,然后再给Jsoncpp解析:
|
|
使用Reader
来读取
和Writer
一样,Reader也已经被抛弃了。但是用起来还是很顺手。用法其实和Writer差不多:
|
|
首先声明Reader对象,然后调用parse
函数,第一个参数是要解析的文本字符串,第二个参数是解析完成之后返回的Json::Value,第三个参数表示是否也解析注释。如果为false则会丢弃注释。
然后你就可以使用Json::Value来获得元素了。
使用CharReaderBuilder
,CharReader
读取
其实和写入一样,首先通过CharReaderBuilder
来设置一些读取设置,然后通过newCharReader()
函数构造一个CharReader,然后解析获得一个Json::Value:
|
|
但是CharReader解析Json有一个很麻烦的事情,就是它的parse函数需要传入要解析文本的第一个字符和最后一个字符,来确定要解析哪一段。这样你就必须在读取json文件的时候顺便将文本长度读取出来(或者你直接用strlen(buffer)也可以)。
parse
函数第一个参数是开始解析的文本,最后一个参数是结束的文本,第三个参数是要返回的Json::Value,最后一个参数是错误信息。
至于CharReaderBuilder的设置,有如下值:
- "collectComments": false or true 是否解析注释,如果allowComments参数为false就无视这个设定
- "allowComments": false or true 是否允许注释
- "strictRoot": false or true 严格要求根元素为数组或者Json对象(严格遵循json格式)
- "allowDroppedNullPlaceholders": false or true 是否丢弃null值
- "allowNumericKeys": false or true 是否允许解析数学类型的键
- "allowSingleQuotes": false or true 是否连同键值对左右的
"
符号一并保留。 - "stackLimit": integer 超出integer大小的话会抛出异常
- "rejectDupKeys": false or true如果为true,当json对象中有重复的键时
parse
函数会返回false - "allowSpecialFloats": false or true是否允许Nan和Infinity
通过Json::Value来获得键值
我们得到了Json::Value,就需要通过Json::Value来获得信息。
先是如下的函数来帮我们判断这个Json::Value对象包含的值类型:
isNull, isBool, isInt, isInt64, isUInt, isUint64, isIntegral, isDouble, isNumeric, isString, isArray, isObject
。
然后你可以通过这些判断来调用一下函数获得对应的值:
asInt, asInt64, asUInt, asUInt64, asLargestInt, asLargestUInt, asFloat, asDouble, asBool, asString, asCString
。
或者通过isMember()
来判断某个键在不在此Value中。
如果你事先已经知道了是什么类型的值,你也可以直接通过下标运算来获得。
或者你也可以通过get()
函数来获得,第一个参数是要获得值的键名,第二个参数为Json::Value,指出如果键不存在的默认返回值。
你也可以通过size()
函数得到数组的大小或则会json对象的值个数。
通过empty()
来判断数组和对象是否为空。
通过isValidIndex()
来判断下标是否越界。
你也可以通过toStyledString()
来返回整个字符串。