Как создать и проанализировать иерархический/вложенный JSON с помощью Poco C++?

Отредактировано, чтобы упростить и показать мой ТОЧНЫЙ код.

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

string name;
std::map<string, string> metaData;

Мне нужно, чтобы JSON был вложенным/иерархическим следующим образом:

{
    "name":"john smith"
    "metadata":
    {
        "age":45,
        "middle_name":"william",
    },
}

Вот мой ТОЧНЫЙ код:

void DeserializeFromJSON(string &jsonString)
{
    // Parse the JSON
    Poco::JSON::Parser jsonParser;
    Poco::Dynamic::Var parsedJSON = jsonParser.parse(jsonString);
    Poco::Dynamic::Var parsedResult = jsonParser.result();

    // Extract the JSON Object
    Poco::DynamicStruct jsonStruct = *parsedResult.extract<Poco::JSON::Object::Ptr>();

    // Get the name
    name = jsonStruct["name"].toString();

    // Get the meta data -- which of these should I use???
    Poco::Dynamic::Var metaVar = jsonStruct["metadata"];
    Poco::JSON::Object metaObj = jsonStruct["metadata"];

    // At this point, exactly what is it I have in 'metaVar' and 'metaObj'?

    // If I try to loop like you say, I get compiler error C2664 in "var.h"
    for (Poco::JSON::Object::ConstIterator itr = jsonObject.begin(), end = jsonObject.end(); itr != end; ++itr)
    {
        string metaName = itr->first;
        string metaValue = itr->second.toString();
    }
}

person Bungles    schedule 14.05.2015    source источник


Ответы (2)


ОБНОВЛЕНИЕ: при сборке этого примера я обнаружил тонкую ошибку; это исправлено в репозитории для предстоящих выпусков 1.6.1 и 1.7.0. Пример ниже отлично работает с более ранними выпусками, просто не используйте порядок сохранения с JSON::Stringifier::stringify() (можно использовать Object::stringify()).

Ну вот; если вы не заботитесь о сохранении порядка вставки записей JSON, ничего не передавайте в конструктор объектов - он будет работать немного лучше:

#include "Poco/JSON/Parser.h"
#include "Poco/JSON/ParseHandler.h"
#include "Poco/JSON/Stringifier.h"

using Poco::JSON::ParseHandler;
using Poco::JSON::Stringifier;
using Poco::JSON::Object;
using Poco::JSON::Parser;
using Poco::Dynamic::Var;
using Poco::DynamicStruct;

void objPrint(Object& obj, const std::string& name = "")
{
    for (Object::ConstIterator it = obj.begin(),
        end = obj.end(); it != end; ++it)
    {
        if (!name.empty()) std::cout << name << ':';
        std::cout << it->first << ':';
        if (it->second.type() == typeid(Object::Ptr))
        {
            Object::Ptr p = it->second.extract<Object::Ptr>();
            objPrint(*p, it->first);
        }
        else
             std::cout << it->second.toString() << std::endl;
    }
}

int main(int, char**)
{
    typedef std::map<std::string, int> PersonMap;

    std::string timeStamp = "2015-05-14T17:47:21.999Z";
    Poco::Int32 identifier = 3;
    std::string name = "john smith";
    PersonMap metaData;
    metaData.insert(PersonMap::value_type("william", 45));

    Object obj(true);
    obj.set("ts", timeStamp);
    obj.set("name", name);
    obj.set("identifier", identifier);
    Object::Ptr pMD = new Poco::JSON::Object(true);
    for (PersonMap::iterator it = metaData.begin(),
        end = metaData.end(); it != end; ++it)
    {
        pMD->set("middle_name", it->first);
        pMD->set("age", it->second);
    }
    obj.set("metadata", pMD);

    std::ostringstream os;
    obj.stringify(os, 2);
    std::cout << os.str() << std::endl;

    Parser parser;
    Var result = parser.parse(os.str());

    Object::Ptr pObj = result.extract<Object::Ptr>();
    objPrint(*pObj);

    return 0;
}
person Alex    schedule 15.05.2015
comment
Измененный вопрос, чтобы показать точный код. Все, что я пытаюсь сделать, это получить «metaName» и «metaValue», как показано. - person Bungles; 18.05.2015
comment
Вы продолжаете менять вопрос, но ответ находится в опубликованном коде. Я обновил его, чтобы точно показать, как (1) создать структуру данных json программно, (2) сериализовать ее в std::string, (3) проанализировать std::string обратно в структуру данных и (4) пройти всю структуру , обнаруживая в нем вложенные объекты JSON. Изучите пример, и вы поймете, как это сделать. - person Alex; 18.05.2015
comment
Я продолжаю повторять вопрос, потому что вы продолжаете не отвечать на него. Ваш код не работает на моем ПК, поэтому единственное, что я могу (и сделал), это опубликовать свой код и попросить вас указать, что не так. Ваш код не имеет для меня никакого смысла, потому что он не делает то, что я пытаюсь сделать. - person Bungles; 18.05.2015
comment
Тогда я не могу вам помочь, извините. Код, который я разместил здесь, работает и делает то, что вы просили. Удачи вам в путешествии. - person Alex; 18.05.2015
comment
То есть вы не можете посмотреть на код вверху этого поста и понять, чем он отличается от того, что вы опубликовали? Ваш пример кода даже не компилируется. - person Bungles; 18.05.2015
comment
Нет простите. Я предлагаю вам прочитать исходный вопрос, который был задан, а затем изучить код, который я вам дал. Он работает и делает то, что вы просили. - person Alex; 18.05.2015
comment
В ответе наверняка есть std::map. Что касается того, насколько сложно перевести объекты it->first и it->second в аналоги std:map, я оставлю вас подумать над этим. - person Alex; 18.05.2015
comment
Действительно? Вздох. Он не ИЗВЛЕЧАЕТСЯ в STD::MAP, в чем и был весь смысл исходного и измененного вопроса. - person Bungles; 18.05.2015
comment
Просто из любопытства, когда вы просите туалет в общественном месте, человек, который дает вам информацию, также должен помогать вам на самом деле использовать его? Конечно, при таком настрое просто направления, где есть место, будет недостаточно. Но отношение было очень воспитательным. Я могу гарантировать, что вы будете ждать очень долго еще один ответ от меня. - person Alex; 18.05.2015
comment
Кроме того, для протокола, @Bungles назвал меня придурком, но комментарий был позже удален. - person Alex; 18.05.2015
comment
Кроме того, для протокола, @Alex поливает грязью. - person Bungles; 18.05.2015
comment
@Alex стоит за всем, что он разместил здесь, за кодом и прочим; без удаленных комментариев и без обзываний. - person Alex; 18.05.2015
comment
Так что это был за маленький дидди о походе в туалет? Если вы прямо не говорите что-то, это не значит, что вы этого не говорили. Личная атака остается личной атакой. Я назвал тебя придурком, потому что ты вел себя элитарно, отвечая на мой вопрос. Удалив его, я вернул личную атаку, не пытаясь ее скрыть. - person Bungles; 18.05.2015
comment
Это была метафора - я указал тебе правильное направление, провел тебя к двери, открыл ее для тебя, но ты расстроился, потому что я не хотел войти с тобой. Поскольку вы мне не платите, я могу перестать вам помогать в любой момент, и вы не имеете права расстраиваться. Я тебе немного помог, на мой взгляд, достаточно, чтобы идти самому. Это вы не выполнили свою часть работы - черт возьми, даже ваш JSON в вопросе недействителен. И теперь я сделал с этим. Я надеюсь, что мод закроет эту тему, потому что я устал от нее. - person Alex; 18.05.2015
comment
Нет, это была личная атака, замаскированная под метафору. Что меня расстроило, так это тон вашего ответа. Ты вообще не проводил меня до двери. На самом деле вы полностью проигнорировали специфику моего вопроса, а затем сказали мне, что это моя вина, что я не понял вашего общего ответа. Я разместил очень конкретный код, который делал вещи очень определенным образом, а вы проигнорировали его и сказали мне, что это не имеет значения. Это не должно расстраивать? - person Bungles; 18.05.2015
comment
Вы специально разместили вопрос о Poco::JSON::Object, который я специально ответил компилируемым и функциональным примером, показывающим, как именно получить доступ как к объектам верхнего уровня, так и к вложенным объектам JSON, а также к дополнению доступа DynamicStruct, которое побудило вас зацепиться за него. В этот момент, возможно, вы подумаете о том, чтобы принять ответ и отправить мне по почте те 500 долларов, обещание которых вы также удалили? - person Alex; 18.05.2015
comment
Я уже заплатил человеку, который фактически ответил на мой вопрос. - person Bungles; 18.05.2015
comment
Я вижу, вы получили ответ, и поэтому вы опубликовали ответ о том, что это невозможно сделать? - person Alex; 18.05.2015
comment
В этих вопросах много неверных предположений, а также здоровая смесь высокомерия и снисходительности. Пар для курса. - person Bungles; 18.05.2015
comment
Спасибо! Кажется, вы хотели написать Var result = parser.parse(os.str());, а не Var result = Parser().parse(os.str());, поскольку вы создали объект Parser parser;. - person fireant; 16.10.2015

Вот что сработало:

// Deserialize from JSON
void DeserializeFromJSON(string &jsonString)
{
    // Parse the JSON
    Poco::JSON::Parser jsonParser;
    Poco::Dynamic::Var parsedJSON = jsonParser.parse(jsonString);
    Poco::Dynamic::Var parsedResult = jsonParser.result();

    // Extract top-level fields
    Poco::DynamicStruct jsonStruct = *parsedResult.extract<Poco::JSON::Object::Ptr>();
    name = jsonStruct["identifier"].toString();

    // Get metadata nested fields
    string keyStr = "metadata";
    Poco::JSON::Object::Ptr jsonObject = parsedResult.extract<Poco::JSON::Object::Ptr>();
    Poco::Dynamic::Var metaVar = jsonObject->get(keyStr);
    Poco::JSON::Object::Ptr metaObj = metaVar.extract<Poco::JSON::Object::Ptr>();
    for (Poco::JSON::Object::ConstIterator itr = metaObj->begin(), end = metaObj->end(); itr != end; ++itr)
        metaData[itr->first] = itr->second.toString();
}

Казалось бы, DynamicStruct нельзя использовать для вложенных полей.

person Bungles    schedule 17.05.2015
comment
Конечно может (и этот комментарий только для предотвращения распространения дезинформации): DynamicStruct nestedStruct = jsonStruct["metadata"].extract<DynamicStruct>(); - person Alex; 18.05.2015
comment
Видишь, это было уже не так сложно, не так ли? - person Bungles; 18.05.2015