C++利用jsoncpp库实现写入和读取json文件
- 1 jsoncpp常用类
- 1.1 Json::Value
- 1.2 Json::Reader
- 1.3 Json::Writer
- 2 json文件
- 3 写json文件
- 3.1 linux存储结果
- 3.2 windows存储结果
- 3 读json文件
- 4 读json字符串
- 参考文章
在C++中使用跨平台的开源库JsonCpp,实现json的序列化和反序列化操作。
1 jsoncpp常用类
1.1 Json::Value
可以表示所有支持的类型:int、double、string、object、array等
节点的类型判断:isNull、isBool、isInt、isArray、isMember、isValidIndex
类型获取:type
类型转换:asInt、asString等
节点获取:get、[]
节点比较:<、<=、>、>=、==、!=
节点操作:compare、swap、removeMember、removeindex、append等函数。
1.2 Json::Reader
将文件流或字符串解析到Json::Value中,主要使用parse函数。
1.3 Json::Writer
将Json::Value转换成字符串流等,Writer类是一个纯虚类,不能直接使用。
使用 Json::Writer 的子类:
Json::FastWriter,将数据写入一行,没有格式
Json::StyledWriter,按json格式化输出,易于阅读
2 json文件
{
"Address": "北京",
"Date": 1998,
"Color": [0.8, 1, 0.5],
"classIds": [
[0],
[0,1]
],
"regions": [
[[420,200],[850,300],[1279,719],[640,719]],
[[0,0],[500,0],[500,719],[0,719]]
],
"Info": {
"Class": "三年级",
"School": "北京一中"
},
"Students": [
{
"Id": 1,
"sex": "男",
"ontime": true,
"time": "2021-01-16"
},
{
"Id": 2,
"sex": "男",
"ontime": true,
"time": "2021-01-16"
}
]
}
3 写json文件
#include"opencv2/opencv.hpp"
#include "json/json.h"
#include <fstream>
int main()
{
std::string strFilePath = "test.json";
Json::Value root;
//string
root["Address"] = "北京";
//int
root["Date"] = 1998;
//array
root["Color"].append(0.8);
root["Color"].append(1.0);
root["Color"].append(0.5);
//array-array
root["classIds"][0].append(0);
root["classIds"][1].append(0);
root["classIds"][1].append(1);
//array-array-array
std::vector<cv::Point> pts1 = { {420,200} ,{850,300},{1279,719},{640,719} };
std::vector<cv::Point> pts2 = { {0,0} ,{500,0},{500,719},{0,719} };
Json::Value region1, region2;
for (auto& pt : pts1)
{
Json::Value jpt;
jpt.append(pt.x);
jpt.append(pt.y);
region1.append(jpt);
}
for (auto& pt : pts2)
{
Json::Value jpt;
jpt.append(pt.x);
jpt.append(pt.y);
region2.append(jpt);
}
root["regions"].append(region1);
root["regions"].append(region2);
//object
root["Info"]["Class"] = "三年级";
root["Info"]["School"] = "北京一中";
//array-object
for (int i = 0; i < 2; i++)
{
root["Students"][i]["Id"] = i + 1;
root["Students"][i]["sex"] = "男";
root["Students"][i]["ontime"] = true;
root["Students"][i]["time"] = "2021-01-16";
}
Json::StreamWriterBuilder builder;
//设置格式化字符串为空,默认设置为以"\t"格式化输出JSON
//builder["indentation"] = "";//节省内存
//JSONCPP默认编码是UTF8,与VS默认编码不一致,当输入中文时会出现乱码
//StreamWriterBuilder提供设置默认编码的参数
builder["emitUTF8"] = true;
std::ofstream outFile(strFilePath);
outFile << Json::writeString(builder, root);
outFile.close();
return 0;
}
在Linux系统运行时,存储的json文件中文正常显示。
在 windows系统运行时,“北京”存储为"\u5317\u4eac",读取时控制台可以正常显示中文字符。
3.1 linux存储结果
3.2 windows存储结果
3 读json文件
#include "json/json.h"
#include <fstream>
#include <Windows.h>
int main()
{
//windows解决控制台中文乱码
//引入Windows.h库,设置字符编码utf-8
SetConsoleOutputCP(CP_UTF8);
std::string strFilePath = "test.json";
Json::Reader json_reader;
Json::Value rootValue;
std::ifstream infile(strFilePath.c_str(), std::ios::binary);
if (!infile.is_open())
{
std::cout << "Open config json file failed!" << std::endl;
return 0;
}
if (json_reader.parse(infile, rootValue))
{
//string
std::string sAddress = rootValue["Address"].asString();
std::cout << "Address = " << sAddress << std::endl;
//int
int nDate = rootValue["Date"].asInt();
std::cout << "Date = " << nDate << std::endl;
//array
Json::Value colorResult = rootValue["Color"];
if (colorResult.isArray())
{
for (unsigned int i = 0; i < colorResult.size(); i++)
{
double dColor = colorResult[i].asDouble();
std::cout << "Color = " << dColor << std::endl;
}
}
//array-array
Json::Value classIds = rootValue["classIds"];
if (classIds.isArray()) {
for (int i = 0; i < classIds.size(); i++)
{
Json::Value classId = classIds[i];//classIds中的第i个classId组合
if (!classId.isArray())
continue;
std::cout << "classIds " << i << " : [ ";
for (int j = 0; j < classId.size(); j++) {
int id = classId[j].asInt();
std::cout << id << ", ";
}
std::cout << "]" << std::endl;
}
}
//array-array-array
Json::Value regions = rootValue["regions"];
if (regions.isArray()) {
for (int i = 0; i < regions.size(); i++) {
std::cout << "region " << i << " : ";
Json::Value region = regions[i];//regions中的第i个region
if (!region.isArray())
continue;
for (int j = 0; j < region.size(); j++)
{
Json::Value pt = region[j]; //region中的第j个点
if (pt.isArray()) {
int x = pt[0].asInt();
int y = pt[1].asInt();
std::cout << "[ " << x << ", " << y << " ],";
}
}
std::cout << std::endl;
}
}
//object
std::string sSchool = rootValue["Info"]["Class"].asString();
std::string sClass = rootValue["Info"]["School"].asString();
std::cout << "Class = " << sClass << std::endl;
std::cout << "School = " << sSchool << std::endl;
// array-object
Json::Value studentResult = rootValue["Students"];
if (studentResult.isArray())
{
for (unsigned int i = 0; i < studentResult.size(); i++)
{
int nId = studentResult[i]["Id"].asInt();
std::string sSex = studentResult[i]["sex"].asString();
bool bOnTime = studentResult[i]["ontime"].asBool();
std::string sTime = studentResult[i]["time"].asString();
std::cout << "Student " << i << " : Id = " << nId << ", sex = " << sSex << ", bOnTime = " << bOnTime << ", Time = " << sTime << std::endl;
}
}
}
else
{
std::cout << "Can not parse Json file!";
}
infile.close();
return 0;
4 读json字符串
数据在“名称/值” 对中,数据由逗号“ , ”分隔,使用斜杆来转义“ \” 字符,大括号 “{} ”保存对象。
json数据如下:
{
"name" : "测试",
"age" : "21",
"sex" : "男"
}
#include "json/json.h"
#include <fstream>
#include <Windows.h>
int main()
{
SetConsoleOutputCP(CP_UTF8);
Json::Reader json_reader;
Json::Value rootValue;
//字符串
std::string str =
"{\"name\":\"测试\",\"age\":21,\"sex\":\"男\"}";
//从字符串中读取数据
if (json_reader.parse(str, rootValue))
{
std::string name = rootValue["name"].asString();
int age = rootValue["age"].asInt();
std::string sex = rootValue["sex"].asString();
std::cout << name + ", " << age << ", " << sex << std::endl;
}
return 0;
参考文章
vs2022控制台输出中文字符&存储中文字符
Jsoncpp用法小结 VS2019
C++利用jsoncpp库实现写入和读取json文件
C++ Builder 生成 json,Json::StreamWriterBuilder 参数详解
C++ Json中文乱码问题