C++ 上 jsoncpp 库使用
C++ 如何安装 jsoncpp,及 jsoncpp 如何使用
如何安装 jsoncpp?
- 从 Tags · open-source-parsers/jsoncpp · GitHub 下载 jsoncpp 的.zip 压缩包
- 解压后,在解压路径下新建 build 文件夹,然后使用 cmake 打开,依次点击 Configure Generate
- 进入 build 目录,找到.sln,使用 VS2019 打开,修改编译环境为 Release x64
- 右键 INSTALL,选择生成
- 生成完成后,第二步截图上的 CMAKE_INSTALL_PREFIX 指定的路径将安装 jsoncpp,确认该路径是否生成
- 打开 VS 工程,在项目属性配置以下信息,完成安装
- C/C++→常规→附加包含目录,填写安装路径的 include 及 include\json 两个路径
- 链接器→常规→附加库目录,添加安装路径的 lib 目录
- 链接器→输入→附加依赖项,添加 jsoncpp.lib
- 将安装目录 bin 目录下的 jsoncpp.dll 拷贝到项目执行路径下
jsoncpp 如何反序列化 json 文件?
- 构建 Json 解析器
1
2Json::CharReaderBuilder rbuilder;
rbuilder.settings_["allowComments"] = true; //读取配置文件中的注释 - 打开文件,按流的方式读入
1
2
3
4
5
6fin.open(readFilePath, ios::in);
if (!fin.is_open())
{
cout << "ReadJsonFromFile Open json file error!" << endl;
return -1;
} - 将文件流输入到解析器,得到读取结果
1
2
3
4
5
6
7
8
9
10
11
12
13JSONCPP_STRING errs;
bool parse_ok = Json::parseFromStream(rbuilder, fin, &jsonContent, &errs); //解析配置文件
if (!parse_ok)
{
cout << "ReadJsonFromFile Parse json file error!" << endl;
fin.close();
return -1;
}
else
{
cout << "ReadJsonFromFile success!" << endl;
}
fin.close();
jsoncpp 如何序列化 json 内容?
- 打开文件流
1
2
3
4
5
6
7fstream f;
f.open(saveFilePath, ios::out | ios::trunc);
if (!f.is_open())
{
cout << "WritrJsonToFile Open file error!" << endl;
return -1;
} - 构建 json 输出解析器
1
2
3
4
5Json::StreamWriterBuilder streamWriteBuilder;
streamWriteBuilder.settings_["emitUTF8"] = true; //key或value中包含中文时,要使用utf-8编码
streamWriteBuilder.settings_["commentStyle"] = "All"; //添加注释情况,All表示所有,None表示不添加
streamWriteBuilder.settings_["precision"] = 4; // 数值的精度
std::unique_ptr writer(streamWriteBuilder.newStreamWriter()); - 将解析得到的流写到文件
1
2writer->write(jsonContent, &f);
f.close();
jsoncpp 如何将 String 转为 json 的键值对?
- 使用 jsoncpp 构建字符解析器
1
2
3Json::CharReaderBuilder charReadBuilder;
charReadBuilder.settings_["allowComments"] = true; //读取配置文件中的注释
Json::CharReader* reader(charReadBuilder.newCharReader()); - 使用解析器解析 String 数据
1
2
3
4
5
6
7
8
9
10
11
12
13const char* stringContent= "{\"Test01\":\"test\",\"Test02\":18}";
JSONCPP_STRING errs;
bool ok = reader->parse(stringContent.c_str(), stringContent.c_str() + std::strlen(stringContent.c_str()), &jsonContent, &errs);
if (ok && errs.size() == 0)
{
cout << "buildJsonFromString success!" << endl;
}
else
{
cout << "buildJsonFromString Parse json file error!" << endl;
return -1;
}
delete reader;
如何解决 jsoncpp 写中文乱码问题?
1 | // 构建Json输出流时提前设置utf-8即可 |
如何使用 jsoncpp 创建 Json 对象?
- 使用 append
1
2
3
4Json::Value resultMapLabel;
resultMapLabel["0"] = "label1";
resultMapLabel["1"] = "label2";
resultMapLabel["2"] = "label3"; - 直接键值对赋值
1
2
3
4onnxJsonContent["requiredGpuMemory"] = "310MiB";
onnxJsonContent["inferTime"] = "100ms";
onnxJsonContent["imageInputWidth"] = 280;
onnxJsonContent["imageInputHeight"] = 280; - 嵌套复用
1
onnxJsonContent["resultMapLabel"] = resultMapLabel;
如何使用 jsoncpp 为 json 文件添加注释?
1
2
3
4
5
6
7// 注意:先添加键值对,在添加注释,否则注释添加失败,因为不知道添加位置
onnxJsonContent["requiredGpuMemory"] = "310MiB";
onnxJsonContent["requiredGpuMemory"].setComment(Json::String("// 模型占用显存空间"), Json::CommentPlacement::commentBefore);
onnxJsonContent["inferTime"] = "100ms";
onnxJsonContent["inferTime"].setComment(Json::String("// 模型推理耗时"), Json::CommentPlacement::commentBefore);
如何遍历 jsoncpp 中的 JsonValue?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18// 本例子遍历最深二层的json文件,更深需进一步嵌套循环
if (jsonContent.size() > 0) {
for (Json::Value::iterator it = jsonContent.begin(); it != jsonContent.end(); it++) {
if ((*it).type() == Json::objectValue) {
Json::Value::Members onnxJsonContentNumber = (*it).getMemberNames();
for (Json::Value::Members::iterator iter = onnxJsonContentNumber.begin(); iter != onnxJsonContentNumber.end(); iter++) {
cout << (*iter) << ":" << (*it)[(*iter)] << endl;
}
}
else
{
cout << (*it) << endl;
}
}
}
else
{
cout << "not found json value"<
如何确保 jsoncpp 序列化时,键值对的顺序按照添加顺序进行存储?
- 暂时无法解决,在 value.h 文件中,json 对象使用 typedef std―map ObjectValues 存储,而 map 是无序的,所以使用 jsoncpp 的进行序列化无法按顺序存储,必须使用自定义的序列化方法,并且创建 json 对象时,需记录创建顺序