一个小工程需要在C++中使用json,于是我找到了库jsoncpp。第一次在Visual Studio中安装和使用jsoncpp库的时踩了一些坑,花了半天的时间解决了问题。写一篇博客来分享jsoncpp的安装与使用方法。
安装 写在开始之前 我的jsoncpp库的版本:jsoncpp-1.8.4
示例项目的名称:jsontest
路径:D:\proj\jsoncppTEST\
必看!必看!必看! 安装过程中将会用到git bash
在安装jsoncpp之前,确保你的Visual Studio安装了英文语言包 ,否则最后一步将会无法执行。如果没有安装英文语言包,请在Visual Studio修改程序 (在程序和功能 里面找)里面添加这个语言包。
直接在github上下载jsoncpp,然后想百(CS)度(DN)上说的那样去做是没法成功的。
那么百(CS)度(DN)上怎么说的?
首先下载jsoncpp这个库
打开jsoncpp\makefiles\vs71\jsoncpp.sln,然后编译以生成json_vc71_libmtd.lib(工程把json_vc71_libmtd.lib生成到了jsoncpp\build\vs71\debug\lib_json下)
然后把jsoncpp\include\json\下的文件以及json_vc71_libmtd.lib复制到工程目录下
把这些文件添加到工程中,并且修改项目属性,修改方法为balabalabalabala…
然后就大功告成
如果这样做,那么恭喜你,VS会亲切地告诉你:
(当然这里使用的是另一个项目)
开始安装 根据github上的jsoncpp库 的官方说明文档README.md ,首先我们打开(或者新建一个)VS项目,然后在终端打开
接着我们会发现左下角多了一个选项卡:开发者PowerShell
现在我们在Powershell里面依次执行以下命令(一条一条复制上去然后一条一条运行):
1 2 3 4 5 git clone https://github.com/Microsoft/vcpkg.git cd vcpkg./bootstrap-vcpkg.sh ./vcpkg integrate install ./vcpkg install jsoncpp
这里再写一遍:如果你的Visual Studio没有安装英文语言包 ,那么请在Visual Studio修改程序 (在程序和功能 里面找)里面添加这个语言包。
这样就可以了,是不是很简单啊(不枉费我半天时间)
使用 关于json json诞生自js,因为二者十分相似,所以相互支持起来非常方便。不过我们在C++中也需要使用json,所以又有大佬专门为C++开发了jsoncpp
json的食用方法 json中仅支持两种结构
name->value,键值对(pair)的集合,一般称为对象(object)
值的有序表,一般称为数组(array)
键值对pair 一个pair的结构通常是:string : value
,pair的对应关系用:
表示,左边的为name,右边的是其对应的值value
一般key使用字符串。也可以使用数字,但是不推荐
value可以是json支持的任何类型,如object、array、string、number、true/false,null
对象object object可以认为是多个pair的集合,其语法为
以{
作为object起始
以}
作为object结束
不同pair之间使用,
分割
object中存储的数据是无序的
例如:
1 2 3 4 { "name" : "jensentsts" , "score" : 114514 }
数组array array是value的有序集合,其语法为
以[
作为array起始
以]
作为array结束
不同array元素之间使用,
分割
建议在array中使用统一的类型,否则解析起来比较麻烦
例如:
1 [ { "name" : "jensentsts" , "score" : 114514 } , { "name" : "LiHua" , "score" : -1 } ]
当然这样写也是合法的:
1 [ "jensentsts" , 233 , null , { "year" : 1919810 } , false ]
注释 与C++一样,使用//
或者是/*
与*/
来写注释
例如:
全部加起来,结果写出来 例如(这是我的VS Code配置):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 { "version" : "0.2.0" , "configurations" : [ { "name" : "(gdb) Launch" , "type" : "cppdbg" , "request" : "launch" , "program" : "${fileDirname}/${fileBasenameNoExtension}.exe" , "args" : [ ] , "stopAtEntry" : false , "cwd" : "${workspaceFolder}" , "environment" : [ ] , "externalConsole" : true , "internalConsoleOptions" : "neverOpen" , "MIMode" : "gdb" , "miDebuggerPath" : "gdb.exe" , "setupCommands" : [ { "description" : "Enable pretty-printing for gdb" , "text" : "-enable-pretty-printing" , "ignoreFailures" : false } ] , "preLaunchTask" : "Compile" } ] }
jsoncpp头文件 使用jsoncpp的任何功能,只需要引入一个头文件就好:
JSON解析 解析json字符串 我们将会使用Json::Reader来解析JSON数据,用Json::Value来存储JSON解析出来的各种值。
先Json::Reader reader;
然后调用reader.parse()
解析JSON数据。如果解析成功,返回false
;否则返回true
。
我们将要处理的json数据:
1 { "name" : "jensentsts" , "score" : 114514 }
示例代码:
1 2 3 4 5 6 7 8 9 10 11 Json::Reader reader; Json::Value root; std::string jsonString = "{\"name\": \"jensentsts\", \"score\": 114514}"; if (reader.parse(jsonString/*或者jsonString.c_str()*/, root)){ std::cerr << "parse failed!" << std::endl; } else{ // 类型一定要正确选择,否则会抛出异常 std::cout << root["name"].asString() << std::endl; // 选择为string类型并输出 std::cout << root["score"].asInt() << std::endl; // 选择为int类型并输出 }
当然了,还可以这样写:
1 2 3 4 5 6 7 8 9 10 11 12 Json::Reader reader; Json::Value root; const char jsonString[] = "{\"name\": \"jensentsts\", \"score\": 114514}"; if (!reader.parse(jsonString, jsonString + sizeof(jsonString), root)){ // 这样就是在字符串之中读取部分文本并且解析 // 类型一定要正确选择,否则会抛出异常 std::cout << root["name"].asString() << std::endl; // 选择为string类型并输出 std::cout << root["score"].asInt() << std::endl; // 选择为int类型并输出 } else{ std::cerr << "parse failed!" << std::endl; }
同样的输出结果:
从json文件中读取并解析 以下代码修改自参考资料1
1 2 3 4 5 { "name" : "tocy" , "age" : 1000 }
下面的代码将其读入并解析
1 2 3 4 5 6 7 8 9 10 11 ifstream ifs("checkjson.json"); assert(ifs.is_open()); Json::Reader reader; Json::Value root; if (reader.parse(ifs, root, false)){ std::cerr << "parse failed!" << std::endl; } else{ std::string name = root["name"].asString(); int age = root["age"].asInt(); }
解析array数据 我们将要解析的json数据:
1 2 3 4 [ { "name" : "Tony" , "salary" : 100 } , { "name" : "Kit" , "salary" : 233 } ]
示例代码:
1 2 3 4 5 6 7 8 9 10 11 std::string json = "[\"Here is data below.\", {\"Tony\": \"\", \"salary\": 100}, {\"name\": \"Kit\", \"salary\": 233}]" Json::Reader reader; Json::Value root; if (!reader.parse(json, root)){ // 在json中,第一项是string,第二、三项是object,下面我们将分别输出它们 std::cout << root[0] << std::endl; size_t count = root.size(); for (size_t i = 1; i < count; ++i){ std::cout << root[i]["name"].asString() << "\'s salary is " << root[i]["salary"].asInt() << "." << std::endl; } }
输出结果:
1 2 3 Here is data below. Tony's salary is 100 . Kit's salary is 233 .
全部加起来,结果写出来 我们将要解析的json数据(放在了jkl.json
中):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 { "package-name" : "jinkela" , "version" : "1.0.0" , "artists" : [ { "name" : "Mei" , "from" : "America" } , { "name" : "Ri" , "from" : "Japan" } , { "name" : "Fei" , "from" : "Aferica" } ] , "prop" : { "name" : "jinkela" , "kind" : "fertilizer" , "cost" : 450 , } }
__ __ __ __:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 void packageInstaller(){ Json::Reader reader; Json::Value root; ifstream ifs("jkl.json"); if (!ifs.is_open()){ std::cerr << "Cannot open the file." << std::endl; return; } if (reader.parse(ifs, root)){ std::cerr << "Failed to parse JSON." << std::endl; return; } std::clog << "Stage Package Installer loaded." << std::endl; std::clog << "Package name: " << root["package-name"].asString() << std::endl; std::clog << "Package version: " << root["version"].asString() << std::endl; size_t count = root["artists"].size(); // "artists" for (size_t i = 0; i < count; ++i){ std::clog << "Artist " << i << "is " << root["artists"][i]["name"].asString() << std::endl; std::clog << "\twho is from " << root["artists"][i]["from"].asString() << std::endl; } // "prop" Json::Value prop = root["prop"]; std::clog << "The prop they need:" << std::endl; std::clog << "name: " << prop["name"].asString() << std::endl; std::clog << "kind: " << prop["kind"].asString() <<std::endl; std::clog << "cost: " << prop["cost"].asInt() << std::endl; }
输出结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 Stage Package Installer loaded. Package name: jinkela Package version: 1.0.0 Artist 0 is Mei who is from America Artist 1 is Ri who is from Japan Artist 2 is Fei who is from Aferica The prop they need: name: jinkela kind: fertilizer cost: 450
小结 解析操作基本上就是这些。
我们通过Json::Reader对象
中的parse()
解析JSON数据,parse()
会自动地吧结果写入传入的Json::Value对象
中。调用parse()
的方法有很多种,一般来说分别是:
parse(C++ stream, Json::Value)
,第一项可以是string
,也可以是ifstream
parse(const char* begin, const char* end, Json::Value)
parse(const char* str, Json::Value)
总之最后一项是Json::Value
。你可能会发现parse()
的最后一项会是collectComments
,这个我还没研究过,咕咕咕(*・ω< )
Json::Value对象
中存储的可能是一个键值对,object,array,也可能只是一个简简单单的string,Number,Boolean等等,我们要通过Json::Value对象.as***()
以在C++中使用他们的值
在示例代码中,我们创建了一个名为root
的变量,并用root
存储JSON数据的“根节点”。在“全部加起来,结果写出来”中,我们也用了一个Json::Value prop
来存储其“子节点”的信息。并通过prop
来访问其下的数据。其实,只要我们调用的不是as***()
,那么我们得到的对象都是Json::Value
类型的
JSON数据封装 这里我们会用Json::Value
来存储JSON中的数据,然后用Json::Writer
来把编辑好的Json::Value
转换为JSON字符串
封装简单的数据 示例代码:
1 2 3 4 5 6 7 8 9 10 11 Json::Value root; Json::Value files; Json::FastWriter writer; root["name"] = "Tony"; root["salary"] = 100; root["msg"] = "work hard"; files[0] = "1.zip"; files[1] = "2.txt"; root["files"] = files; std::string jsonFile = writer.write(root); std::cout << jsonFile << std::endl;
封装内嵌object的array 其实和上边那个例子的过程一样。只要你能明白两点
对着Json::Value对象
直接去赋值
array和object的调用方法和使用方法大差不差
咕咕咕
参考资料
json简介及JsonCpp用法
github上jsoncpp/README.md
百度得到的CSDN博客