Как добавить в json файл в указанной c позиции - PullRequest
0 голосов
/ 14 февраля 2020

Я пытаюсь добавить JSON объекты в файл в указанной позиции c, но я не могу сделать это как требуется. Я получаю результат, но без ",", разделяя значения, поэтому они являются отдельными JSON объектами.

Я хочу, чтобы l oop через 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"
    }
  ]
}

Обновленный код: после полезного ввода Ботье.

     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;
    }

Надеюсь, что это поможет другим.

Ответы [ 2 ]

1 голос
/ 14 февраля 2020

Как я понимаю ваш вопрос, вы хотите сделать несколько 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;
}
0 голосов
/ 14 февраля 2020

Предположим, что:

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 данные.

...