-2

我正在尝试将 JSON 对象附加到特定位置的文件中,但我无法按要求执行此操作。我得到了结果,但没有“,”分隔值,因此它们是单独的 JSON 对象。

我想遍历 JSON 对象并将结果附加到文件中并用“,”分隔它,它是一个有效的 JSON。这是我尝试过的


auto js_text = R"(
{
  "a": "all_items",
  "b": []
}
        )";
    std::ofstream js_file("test.json");
    js_file << std::setw(4) << js_text << std::endl;
    std::ifstream in("test4.json");
    json js_file = json::parse(in);
    std::ifstream load_url("url_file.json");
    json url_file = json::parse(load_url);
   for (auto& endpoint : url_file["url_list"])
        {
    std::string url = endpoint["url"].get<std::string>(); 
    auto r = cpr::Get(cpr::Url{ url }); 
    json j = json::parse(r.text); // r gets a nested json objects from parsed url
    for (auto& td : j["b"])    
     {    
      json value = j["b"][0];
      json data = js_file;
      data["b"][0] = value;
      std::ofstream output;
      output.open("test.json",std::ios_base::app );
      output << std::setw(4) << data << std::endl;
}

我想要的结果是

{
  "a": "all_items",
  "b": [
    {
      "c": "xxx",
      "d": "yyy"
    },
    {
      "e": "zzz"
    }
  ]
}

更新代码:在 Botje 有价值的输入之后。

     auto js_text = R"(
        {
           "a": "abc",
             "b": [ ]
           }
           )";

    json js_file = json::parse(js_text);

     std::ifstream load_url("url_file.json");
    json url_file = json::parse(load_url);

    for (auto& endpoint : url_file["url_list"])
     {
      std::string url = endpoint["url"].get<std::string>(); 
      auto r = cpr::Get(cpr::Url{ url }); 
      json j = json::parse(r.text); // j contains results from multiple HTTP requests that has json objects.
       for (auto& elem : j["b"])
            {
              json jd = j["b"];
              js_file["b"].emplace_back(std::move(td));
              std::cout << "jd:" << jd.dump(4) << std::endl;
         }
       }

      std::ofstream output;
      output.open("test.json",std::ios_base::app );
      output << std::setw(4) << js_file << std::endl;
    }

希望这对其他人有帮助。

4

2 回答 2

1

据我了解您的问题,您希望发出多个 HTTP 请求并将每个响应的"b"键下的所有对象收集到一个数组中。

在这里,我们跳过 HTTP 部分并假设 的每个元素r_texts都是一个响应对象。

std::vector<std::string> r_texts = {
    R"({
        "b": [{
            "c": "xxx",
            "d": "yyy"
        }]
    })",
    R"({
        "b": [{
            "e": "zzz"
        }]
    })",
};

这会产生您想要的输出,然后:

auto js_text = R"(
{
  "a": "abc",
  "b": []
}
)";

int main() {
    json js_file = json::parse(js_text);
    for (auto& r_text: r_texts) {
        // r_text is now the contents of one "HTTP response"
        json j = json::parse(r_text);
        // Loop over all objects inside the "b" key
        for (auto & elem: j["b"]) {
            // And use emplace_back+move to detach the object from `j`
            // and move it to the back of `js_file["b"]`.
            js_file["b"].emplace_back(std::move(elem));
        }
    }

    std::ofstream output;
    output.open("test.json",std::ios_base::app );
    output << std::setw(4) << js_file << std::endl;
}
于 2020-02-14T13:21:37.963 回答
0

让我们假设:

std::string original_string;  // Original file contents as a string
json original_json; // JSON value parsed from original_string
json updated_json;  // original_json but updated with new values

然后你得到这样的字符串表示:

std::string updated_string = updated_json.dump();

现在,一次比较两个字符串字符,直到你得到不同。这是您可以写入文件新内容的偏移量。

size_t update_offset = 0;
for (size_t i = 0; i < original_string.size(); ++i) {
  if (i < updated_string.size()) {
    // Update is shorter than original, something is wrong
  }
  if (original_string[i] != updated_string[i]) {
    update_offset = i;
    break;
  }
}

此时,update_offset将有两个字符串之间共有的字节数;这之后的一切都改变了。现在,我们打开原始文件,寻找这个偏移量并写入字符串的其余部分。

std::ofstream output{"test.json", std::ofstream::out};
output.seekp(update_offset);
output << updated_string.substr(update_offset);
output.close();

上述顺序确保输出文件的内容是您的 JSON 数据的语法正确表示。

于 2020-02-14T17:34:09.767 回答