Как перебрать JSON в JSON для современного c ++ - PullRequest
1 голос
/ 30 марта 2019

Я хотел бы перебрать каждую из записей в объекте json, но я получаю одну непонятную ошибку за другой. Как исправить следующий пример?

#include <iostream>

#include <nlohmann/json.hpp>

using json = nlohmann::json;

void bla(std::string a) {
    std::cout << a << '\n'; 
}

int main() {
    json RecentFiles;

    RecentFiles["1"]["Name"] = "test1.txt";
    RecentFiles["1"]["Last modified"] = "monday";
    RecentFiles["1"]["Score"] = 5.0f;

    RecentFiles["2"]["Name"] = "test2.txt";
    RecentFiles["2"]["Last modified"] = "tuesday";
    RecentFiles["2"]["Score"] = 5.0f;


    for (auto it = RecentFiles.begin(); it != RecentFiles.end(); ++it) {
           bla("JSON: Recent file = " + it.value()["Name"]);    
    }

    std::cout << RecentFiles; }

Ошибка:

prog.cc: In function 'int main()':
prog.cc:18:31: error: invalid conversion from 'const char*' to 'nlohmann::detail::iter_impl<nlohmann::basic_json<> >::difference_type {aka long int}' [-fpermissive]
         std::cout << it["Name"];
                               ^
In file included from prog.cc:2:0:
./nlohmann/json.hpp:4418:15: note: initializing argument 1 of 'nlohmann::detail::iter_impl<BasicJsonType>::reference nlohmann::detail::iter_impl<BasicJsonType>::operator[](nlohmann::detail::iter_impl<BasicJsonType>::difference_type) const [with BasicJsonType = nlohmann::basic_json<>; nlohmann::detail::iter_impl<BasicJsonType>::reference = nlohmann::basic_json<>&; nlohmann::detail::iter_impl<BasicJsonType>::difference_type = long int]'
     reference operator[](difference_type n) const
               ^

Выше сделано в песочнице

https://wandbox.org/permlink/LNck7Gktm14bmPy0

Это не настоящий код, который я использую, я просто хочу посмотреть, смогу ли я понять, как выполнять различные основные вещи, которые мне нужно делать с JSON.

В настоящее время я так мало понимаю, что не знаю, является ли то, что я делаю, по существу правильно, а просто ломается из-за чего-то глупого или я делаю что-то принципиально неправильное.

1 Ответ

2 голосов
/ 02 апреля 2019

Библиотека nlohmann json позиционирует себя как «JSON для современного C ++» и стремится вести себя «как контейнер STL».Однако в стандартной библиотеке C ++ нет контейнера, который был бы «векторным» и «подобным карте» и который поддерживал бы итераторы начала / конца для значений, и итераторы начала / конца для пар ключ / значение.Поэтому нужно что-то новое.

Первоначальным решением nlohmann было скопировать подход jsoncpp , который поддерживает итераторы начала / конца для массивов json, и добавляет явно нестандартную функцию key() китератор для поддержки объектов json.Таким образом, вы могли бы написать

for (auto it = RecentFiles.begin(); it != RecentFiles.end(); ++it)
{
    std::cout << it.key() << "\n";
    std::cout << (*it)["Name"].get<std::string>() << "\n";
    std::cout << (*it)["Last modified"].get<std::string>() << "\n";
}

Но, будучи нестандартным способом итерации по ключу / значениям, он не имеет стандартной поддержки библиотеки для диапазона, основанного на циклах по ключу / значениям.

nlohmannпозже добавлена ​​функция json::items(), которая поддерживает итерацию по объектам json со стандартными итераторами и которая поддерживает стандартную библиотеку для поддержки диапазона, основанного на циклах, а именно:

int main()
{
    json RecentFiles;

    RecentFiles["1"]["Name"] = "test1.txt";
    RecentFiles["1"]["Last modified"] = "monday";
    RecentFiles["1"]["Score"] = 5.0f;

    RecentFiles["2"]["Name"] = "test2.txt";
    RecentFiles["2"]["Last modified"] = "tuesday";
    RecentFiles["2"]["Score"] = 5.0f;

    for (const auto& item : RecentFiles.items())
    {
        std::cout << item.key() << "\n";
        for (const auto& val : item.value().items())
        {
            std::cout << "  " << val.key() << ": " << val.value() << "\n";
        }
    }
    std::cout << "\nor\n\n";
    for (const auto& item : RecentFiles.items())
    {
        std::cout << item.key() << "\n";
        std::cout << "  " << item.value()["Name"].get<std::string>() << "\n";
        std::cout << "  " << item.value()["Last modified"].get<std::string>() << "\n";
        std::cout << "  " << item.value()["Score"].get<double>() << "\n";
    }
}

Вывод:

1
  Last modified: "monday"
  Name: "test1.txt"
  Score: 5.0
2
  Last modified: "tuesday"
  Name: "test2.txt"
  Score: 5.0

or

1
  test1.txt
  monday
  5
2
  test2.txt
  tuesday
  5
...