Разбор строки JSON с помощью jsoncpp

Я пытаюсь разобрать строку JSON, закодированную с помощью PHP и отправленную по TCP клиенту C++.

Мои строки JSON выглядят так:

{"1":{"name":"MIKE","surname":"TAYLOR"},"2":{"name":"TOM","surname":"JERRY"}}

В клиенте C++ я использую библиотеки jsoncpp:

void decode()
{
    string text =     {"1":{"name":"MIKE","surname":"TAYLOR"},"2":{"name":"TOM","surname":"JERRY"}};
    Json::Value root;
    Json::Reader reader;
    bool parsingSuccessful = reader.parse( text, root );
    if ( !parsingSuccessful )
    {
        cout << "Error parsing the string" << endl;
    }
    const Json::Value mynames = root["name"];
    for ( int index = 0; index < mynames.size(); ++index )  
    {
        cout << mynames[index] << endl;
    }
}

Проблема в том, что я ничего не получаю на выходе, даже ошибки синтаксического анализа (если есть). Не могли бы вы помочь мне понять, что я делаю неправильно?


person Podarce    schedule 14.11.2017    source источник
comment
этот код даже не скомпилируется. Прежде всего, вам нужно преобразовать строку json в строку C++. При необходимости для больших строк обратитесь к решению link.   -  person kalimba    schedule 14.11.2017
comment
@kalimba Вы абсолютно правы. Я разбираю tcp-поток, но написал функцию со строкой, объясняющую написанный мной код. Я забыл escape-последовательность. Спасибо за голову.   -  person Podarce    schedule 14.11.2017


Ответы (2)


Ваша проблема: нет root["name"]. Ваш документ должен быть таким:

{ "people": [{"id": 1, "name":"MIKE","surname":"TAYLOR"}, {"id": 2, "name":"TOM","surname":"JERRY"} ]}

И ваш код такой:

void decode()
{
    string text ="{ \"people\": [{\"id\": 1, \"name\":\"MIKE\",\"surname\":\"TAYLOR\"}, {\"id\": 2, \"name\":\"TOM\",\"surname\":\"JERRY\"} ]}";
    Json::Value root;
    Json::Reader reader;
    bool parsingSuccessful = reader.parse( text, root );
    if ( !parsingSuccessful )
    {
        cout << "Error parsing the string" << endl;
    }

    const Json::Value mynames = root["people"];

    for ( int index = 0; index < mynames.size(); ++index )
    {
        cout << mynames[index] << endl;
    }
}

Если вы хотите сохранить свои данные как есть:

void decode()
{
  //string text ="{ \"people\": [{\"id\": 1, \"name\":\"MIKE\",\"surname\":\"TAYLOR\"}, {\"id\": 2, \"name\":\"TOM\",\"surname\":\"JERRY\"} ]}";
  string text ="{ \"1\": {\"name\":\"MIKE\",\"surname\":\"TAYLOR\"}, \"2\": {\"name\":\"TOM\",\"surname\":\"JERRY\"} }";
  Json::Value root;
  Json::Reader reader;
  bool parsingSuccessful = reader.parse( text, root );
  if ( !parsingSuccessful )
  {
    cout << "Error parsing the string" << endl;
  }

  for( Json::Value::const_iterator outer = root.begin() ; outer != root.end() ; outer++ )
  {
    for( Json::Value::const_iterator inner = (*outer).begin() ; inner!= (*outer).end() ; inner++ )
    {
      cout << inner.key() << ": " << *inner << endl;
    }
  }
}

Обходите корневой объект напрямую, используя итераторы (не рассматривайте его как массив.

Если Json::Reader не работает, попробуйте Json::CharReader:

void decode()
{
  string text ="{\"1\":{\"name\":\"MIKE\",\"surname\":\"TAYLOR\"},\"2\":{\"name\":\"TOM\",\"surname\":\"JERRY\"}}";

  Json::CharReaderBuilder builder;
  Json::CharReader * reader = builder.newCharReader();

  Json::Value root;
  string errors;

  bool parsingSuccessful = reader->parse(text.c_str(), text.c_str() + text.size(), &root, &errors);
  delete reader;

  if ( !parsingSuccessful )
  {
    cout << text << endl;
    cout << errors << endl;
  }

  for( Json::Value::const_iterator outer = root.begin() ; outer != root.end() ; outer++ )
  {
    for( Json::Value::const_iterator inner = (*outer).begin() ; inner!= (*outer).end() ; inner++ )
    {
      cout << inner.key() << ": " << *inner << endl;
    }
  }
}
person p-a-o-l-o    schedule 14.11.2017
comment
Спасибо за ваш ответ, сэр. У меня есть несколько вопросов по данному ответу, пожалуйста. 1) зачем мне писать такую ​​текстовую строку? Моя строка исходит непосредственно из php json_encode, поэтому она должна быть правильной 2) Если я хочу сохранить ассоциативный массив как 1:{},2:{} , могу ли я сделать это и просто добавить корневых людей? Я немного смущен. - person Podarce; 14.11.2017
comment
Сделал несколько тестов с кодом, проблема в bool parsingSuccessful = reader.parse( text, root ); Похоже, за этой строкой ничего не выполняется. Может быть, это связано с устаревшим использованием Json::Reader reader? Обратите внимание, что у меня нет ошибок компилятора. - person Podarce; 14.11.2017
comment
Добавлен пример на основе CharReader. - person p-a-o-l-o; 14.11.2017
comment
здесь есть еще один пример: neverfriday.com/2013/07/26/learning-jsoncpp< /а> - person ; 17.04.2018
comment
Используйте функцию C++11: префикс R для создания необработанной строки. - person isnullxbh; 20.04.2018
comment
@isnullxbh совершенно прав, строку данных намного проще написать без всего этого утомительного экранирования как string text = R"json({"1":{"name":"MIKE","surname":"TAYLOR"}, "2":{"name":"TOM","surname":"JERRY"}})json"; - person FeRD; 20.06.2019
comment
Json::Reader() отображается как устаревший; используйте CharReader и CharReaderBuilder. - person Technophile; 11.03.2021

Вы также можете прочитать из строкового потока:

std::stringstream sstr(stringJson);
Json::Value json;
sstr >> json;
person waynix    schedule 02.11.2018