ToB企服应用市场:ToB评测及商务社交产业平台

标题: 【Jsoncpp】manipulating JSON data in C++ [打印本页]

作者: 缠丝猫    时间: 2025-1-9 02:42
标题: 【Jsoncpp】manipulating JSON data in C++
源代码


  1. #include <iostream>  // 引入输入输出流库,用于标准输入输出操作
  2. #include <fstream>   // 引入文件流库,用于文件读写操作
  3. #include <json/json.h>  // 引入JSON库,用于解析和操作JSON数据
  4. using namespace std;  // 使用标准命名空间,避免每次调用标准库函数时都要加std::
  5. int main()
  6. {
  7.     Json::Value root;  // 创建一个Json::Value对象,用于存储解析后的JSON数据
  8.     ifstream ifs;  // 创建一个输入文件流对象,用于读取文件
  9.     ifs.open("profile.json");  // 打开名为"profile.json"的文件
  10.     Json::CharReaderBuilder builder;  // 创建一个JSON解析器的构建器对象
  11.     builder["collectComments"] = true;  // 设置解析器在解析时收集注释
  12.     JSONCPP_STRING errs;  // 创建一个字符串对象,用于存储解析过程中可能产生的错误信息
  13.     // 使用解析器从文件流中解析JSON数据,并将结果存储在root对象中
  14.     // 如果解析失败,输出错误信息并返回EXIT_FAILURE
  15.     if (!parseFromStream(builder, ifs, &root, &errs))
  16.     {
  17.         std::cout << errs << std::endl;  // 输出错误信息
  18.         return EXIT_FAILURE;  // 返回程序失败状态
  19.     }
  20.     Json::Value::iterator itr = root.begin();  // 创建一个迭代器,指向JSON对象的起始位置
  21.     int i = 0;  // 初始化一个计数器,用于遍历JSON对象的成员
  22.     string name;  // 创建一个字符串对象,用于存储JSON对象的成员名称
  23.     // 遍历JSON对象的每个成员
  24.     for (itr = root.begin(); itr != root.end(); itr++)
  25.     {
  26.         name = root.getMemberNames()[i];  // 获取当前成员的名称
  27.         // 如果当前成员的值是一个数组(大小大于1),则遍历数组中的每个元素
  28.         if (root[name].size() > 1) {
  29.             for (auto x : root[name]) {
  30.                 cout << name << ": " << x << endl;  // 输出成员名称和数组中的每个元素
  31.             }
  32.         }
  33.         else {
  34.             cout << name + " ";  // 输出成员名称
  35.             cout << root[name] << endl;  // 输出成员的值
  36.         }
  37.         i++;  // 计数器加1,准备处理下一个成员
  38.     }
  39. }
复制代码
json内容为:

  1. {"isbn": "123-456-789",
  2.     "author":
  3.         {
  4.             "lastname": "Doe",
  5.             "firstname" : "Jane"
  6.         },
  7.     "editor":
  8.         {
  9.             "lastname": "Smith",
  10.             "firstname": "Jane"
  11.         },
  12.     "title": "The Ultimate Database Study Guide",
  13.     "category": ["Non-Fiction", "Technology"]
  14. }
复制代码

输出结果:

author: “Jane”
author: “Doe”
category: “Non-Fiction”
category: “Technology”
editor: “Jane”
editor: “Smith”
isbn “123-456-789”
title “The Ultimate Database Study Guide”
为什么没有按json顺序呢?

JSON 是一种无序的数据结构,Json::Value 在解析 JSON 文件时并不会保留原始的顺序。因此,当你遍历 Json::Value 对象时,成员的顺序可能与 JSON 文件中的顺序不一致。
原因分析:


如何保持顺序?

如果你需要保持 JSON 文件中的原始顺序,可以尝试以下方法:
方法 1:使用有序的 JSON 库

某些 JSON 库支持有序的 JSON 解析。例如,nlohmann::json(一个盛行的 C++ JSON 库)可以保留 JSON 文件中的键值对顺序。
方法 2:手动指定顺序

如果你知道 JSON 文件的结构,可以手动指定遍历的顺序。例如:
  1. std::vector<std::string> keys = {"isbn", "author", "editor", "title", "category"};
  2. for (const auto& key : keys) {
  3.     if (root.isMember(key)) {
  4.         if (root[key].isArray()) {
  5.             for (const auto& item : root[key]) {
  6.                 std::cout << key << ": " << item << std::endl;
  7.             }
  8.         } else {
  9.             std::cout << key << " " << root[key] << std::endl;
  10.         }
  11.     }
  12. }
复制代码
方法 3:修改代码逻辑

如果你盼望按照 JSON 文件中的顺序输出,可以修改代码逻辑,直接按照 getMemberNames() 的顺序输出,而不是依赖迭代器:
  1. for (size_t i = 0; i < root.size(); ++i) {
  2.     std::string name = root.getMemberNames()[i];
  3.     if (root[name].isArray()) {
  4.         for (const auto& item : root[name]) {
  5.             std::cout << name << ": " << item << std::endl;
  6.         }
  7.     } else {
  8.         std::cout << name << " " << root[name] << std::endl;
  9.     }
  10. }
复制代码

为什么输出结果中嵌套对象被拆开?

在你的输出结果中,author 和 editor 被拆开为多个键值对,这是因为代码中对嵌套对象的处理逻辑有问题。详细来说:

修正代码:

如果你盼望准确输出嵌套对象的结构,可以修改代码逻辑,递归处理嵌套对象。例如:
  1. void printJsonValue(const Json::Value& value, const std::string& name = "") {
  2.     if (value.isObject()) {
  3.         for (const auto& key : value.getMemberNames()) {
  4.             printJsonValue(value[key], name.empty() ? key : name + "." + key);
  5.         }
  6.     } else if (value.isArray()) {
  7.         for (const auto& item : value) {
  8.             printJsonValue(item, name);
  9.         }
  10.     } else {
  11.         std::cout << name << " " << value << std::endl;
  12.     }
  13. }
  14. int main() {
  15.     Json::Value root;
  16.     std::ifstream ifs("profile.json");
  17.     Json::CharReaderBuilder builder;
  18.     JSONCPP_STRING errs;
  19.     if (!parseFromStream(builder, ifs, &root, &errs)) {
  20.         std::cout << errs << std::endl;
  21.         return EXIT_FAILURE;
  22.     }
  23.     printJsonValue(root);
  24.     return 0;
  25. }
复制代码
修正后的输出:

  1. isbn "123-456-789"
  2. author.lastname "Doe"
  3. author.firstname "Jane"
  4. editor.lastname "Smith"
  5. editor.firstname "Jane"
  6. title "The Ultimate Database Study Guide"
  7. category "Non-Fiction"
  8. category "Technology"
复制代码

总结:


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4