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
    2
    Json::CharReaderBuilder rbuilder;
    rbuilder.settings_["allowComments"] = true; //读取配置文件中的注释
  • 打开文件,按流的方式读入
    1
    2
    3
    4
    5
    6
    fin.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
    13
    JSONCPP_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
    7
    fstream 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
    5
    Json::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
    2
    writer->write(jsonContent, &f);
    f.close();

jsoncpp 如何将 String 转为 json 的键值对?

  • 使用 jsoncpp 构建字符解析器
    1
    2
    3
    Json::CharReaderBuilder charReadBuilder;
    charReadBuilder.settings_["allowComments"] = true; //读取配置文件中的注释
    Json::CharReader* reader(charReadBuilder.newCharReader());
  • 使用解析器解析 String 数据
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    const 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 构建Json输出流时提前设置utf-8即可
fstream f;
f.open(saveFilePath, ios::out | ios::trunc);
if (!f.is_open())
{
cout << "WritrJsonToFile Open file error!" << endl;
return -1;
}
Json::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());
writer->write(jsonContent, &f);
f.close();

如何使用 jsoncpp 创建 Json 对象?

  • 使用 append
    1
    2
    3
    4
    Json::Value resultMapLabel;
    resultMapLabel["0"] = "label1";
    resultMapLabel["1"] = "label2";
    resultMapLabel["2"] = "label3";
  • 直接键值对赋值
    1
    2
    3
    4
    onnxJsonContent["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 对象时,需记录创建顺序