什么是 JSON ?
w3c的标准说明如下:
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。 易于人阅读和编写。同时也易于机器解析和生成。 它基于JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。 这些特性使json成为理想的数据交换语言。
所以几乎所有的语言都会有支持json格式转化的库。
json的格式只有两种,所以非常简单方便:
键值对
对象是一个无序的“‘名称/值’对”集合。一个对象以“{”开始,“}”结束。每个“名称”后跟一个“:”;“键值对”之间使用“,”分隔。
数组
数组是值(value)的有序集合。一个数组以“[”开始,“]”结束。值之间使用“,”分隔。
{
"employees": [
{
"firstName": "Bill",
"lastName": "Gates"
},
{
"firstName": "George",
"lastName": "Bush"
},
{
"firstName": "Thomas",
"lastName": "Carter"
}
]
}
要注意的是,每一个非数值的字符串都应当带引号,否则标准的解析库是无法解析的。
网上也有很多json的在线格式化的网站,在遇到json无法解析的时候可以去那里找找错。
最后需要注意的是,json里的数字都是双精浮点数,因此无法精确的表示 Long 型。在存储大 Long 型数据的时候要小心,不要丢失精度了。
JSON全称为JavaScript Object Notation,它是一种轻量级的数据交换格式,易于阅读、编写、解析。Jsoncpp是c++解析JSON串常用的解析库之一。
目前代码维护在github。
首先从github下载最新版zip:
https://github.com/open-source-parsers/jsoncpp/releases?spm=a2c4e.10696291.0.0.430919a44F1Wlf
接着,将其解压。
Win10 + VS2019 community。
步骤1:编译生成lib
在VS 2019中打开E:\jsoncpp-0.10.7\makefiles\msvc2010下的jsoncpp.sln。右键->重新生成解决方案。此时,会在目录jsoncpp-0.10.7\makefiles\msvc2010\Debug下生成lib_json.lib文件。
步骤2:将所需文件添加至自己的工程
将步骤1生成的lib_json.lib文件和目录jsoncpp-0.10.7下的include文件夹拷贝至自己的项目/工程目录下:
这时在vs的目录列表里是看不到这个目录的,在如下图工具栏中点击图标【显示所有文件】,就可以看到新增的目录了:
这时实际上还没有真正地加入到工程中来,相关图标是红色的,要在工程目录上右键选择【包括在项目中】即可。
步骤3:设置工程属性
工程必须是win32;
工程->属性->配置属性->c/c+±>代码生成->运行库,设置运行库为多线程调试 (/MTd);
步骤4:测试使用
在JsonTest2中JsonTest2.cpp中添加测试代码(写json文件):
#include
#include "include/json/json.h"
using namespace std;
#pragma comment(lib, "json_vc71_libmtd.lib")
int main()
{
Json::Value root;
root["occupatio"] = "paladin";
root["camp"] = "alliance";
root["role_id"] = 1;
Json::StyledWriter writer;
ofstream os;
os.open("test.json");
os << writer.write(root);
os.close();
return 0;
}
编译运行后,工程目录下生成test.json文件。
{
“id” : 123,
"name" : "wu"
}
我们直接将上面的数据初始化到到string对象中,方便解析,后面都是如此。
std::string json = "{\"id\" : 123, \"name\" : \"wu\"}";
Json::Reader reader;
Json::Value root;
std::string name;
int id = 0;
if (reader.parse(json, root)) // reader将Json字符串解析到root,root将包含Json里所有子元素
{
name = root["name"].asString();
id = root["id"].asInt();
}
[ { "id" : 1, "name" : "wu"}, {"id":2, "name" : "tan"} ]
解析方法如下:
std::string json = "[ {\"id\" : 1, \"name\" : \"wu\"}, {\"id\" : 2, \"name\" : \"tan\"} ]";
Json::Reader reader;
Json::Value root;
std::string name;
int id = 0;
std::map mapJson;
if (reader.parse(json, root)) // reader将Json字符串解析到root,root将包含Json里所有子元素
{
for (int i = 0; i < root.size(); ++i)
{
name = root[i]["name"].asString();
id = root[i]["id"].asInt();
mapJson[id] = name;
}
}
如果是这样的数组:
{
“id” : [1, 2],
"name" : ["wu", "tan"]
}
解析方法如下:
std::string json = "{\"id\" : [1, 2], \"name\" : [\"wu\", \"tan\"] } ";
Json::Reader reader;
Json::Value root;
std::string name;
int id = 0;
if (reader.parse(json, root)) // reader将Json字符串解析到root,root将包含Json里所有子元素
{
for (int i = 0; i < root["id"].size(); ++i)
{
id = root["id"][i].asInt();
}
for (int i = 0; i < root["name"].size(); ++i)
{
name = root["name"][i].asString();
}
}
这种情况其实和上一种是类似的。
为了简便,我们嵌套两层。
{
"id" : 1,
"data" : {
"name" : "wu",
“age” : 26
}
}
其实这种情况和第一种的类似,只是通过root[“key”]取到的还是键值对,继续通过key取值即可。
基本上再复杂的数据格式也是上面几种情况的组合而已。
解析方法如下:
std::string json = "{\"id\" : 1, \"data\" : { \"name\" : \"wu\", \"age\" : 26 } }";
Json::Reader reader;
Json::Value root;
std::string name;
int id = 0;
int age = 0;
if (reader.parse(json, root)) // reader将Json字符串解析到root,root将包含Json里所有子元素
{
id = root["id"].asInt();
name = root["data"]["name"].asString();
age = root["data"]["age"].asInt();
}
{
“id” : 123,
"name" : "wu"
}
生成方法如下:
Json::Value root;
root["id"] = 123;
root["name"] = "wu";
std::string json = root.toStyledString();
我们会将生成的json对象序列化到string对象中去,后面也是如此。
[ { "id" : 1, "name" : "wu"}, {"id":2, "name" : "tan"} ]
生成方法如下:
Json::Value root;
for (int i = 0; i < 2; ++i)
{
root[i]["id"] = i + 1;
if (0 == i)
{
root[i]["name"] = "wu";
}
else
{
root[i]["name"] = "tan";
}
}
std::string json = root.toStyledString();
还可以这样生成:
Json::Value root;
Json::Value item;
for (int i = 0; i < 2; ++i)
{
item["id"] = i + 1;
if (0 == i)
{
item["name"] = "wu";
}
else
{
item["name"] = "tan";
}
root.append(item);
}
std::string json = root.toStyledString();
1. {
2.
3. “id” : [1, 2],
4.
5. "name" : ["wu", "tan"]
6.
7. }
生成方法如下:
Json::Value root;
for (int i = 0; i < 2; ++i)
{
root["id"].append(i);
if (0 == i)
{
root["name"].append("wu");
}
else
{
root["name"].append("tan");
}
}
std::string json = root.toStyledString();
为了简便,我们嵌套两层。
{
"id" : 1,
"data" : {
"name" : "wu",
“age” : 26
}
}
生成方法如下:
Json::Value root;
root["id"] = 1;
root["data"]["name"] = "wu";
root["data"]["age"] = 26;
std::string json = root.toStyledString();
其实解析和生成json是互逆的,只要明白这几种情况,其他的无非是这几种情况的各种组合,原理是一样的。
Jsoncpp为Chromium自带的第三方库,位于目录:src/third_party/jsoncpp。
使用时,需在当前模块的头文件中添加头文件:
#include "third_party/jsoncpp/source/include/json/json.h"
使用时,需在当前模块的BUILD.gn文件中添加deps:
deps += [
"//third_party/jsoncpp",
]
需重新编译当前模块,假设当前模块为content:
ninja content