1

This is related to another question I asked, but much more specific. I need to deserialize a std::map from my JSON data.

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

I've tried many, many ways to do this and nothing seems to work. Based on answers to a prior thread, I thought this code should work.

std::map myMap;
std::string jsonString; // string containing the above JSON
Poco::JSON::Parser jsonParser;
Poco::Dynamic::Var parsedJSON = jsonParser.parse(jsonString);
Poco::Dynamic::Var parsedResult = jsonParser.result();
Poco::DynamicStruct jsonStruct = *parsedResult.extract<Poco::JSON::Object::Ptr>();
Poco::Dynamic::Var mapVar = jsonStruct["stdmap_data"];
for (Poco::Dynamic::Var::ConstIterator itr = mapVar.begin(), end = mapVar.end(); itr != end; ++itr)
    myMap[itr->first().toString()] = itr->second().toString();

Unfortunately, this iterator does not have "first" and "second" members. I've tried DynamicStruct (same problem) and JSON::Object (can't/won't convert from jsonStruct["stdmap_data"]).

This seems like something VERY common in JSON data, so I'd be shocked if Poco C++ can't do it. Anyone know how it should be done?

Bungles
  • 1,969
  • 2
  • 25
  • 54

2 Answers2

0

Answered here.

For reference, here is the function snippet that will print out any object, including the nested ones:

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;
    }
}
Community
  • 1
  • 1
Alex
  • 5,159
  • 4
  • 25
  • 33
  • Which of my variables above am I supposed to pass into the 'objPrint' function? There is no JSON::Object for me to pass into the function. – Bungles May 17 '15 at 20:32
  • This code does not answer the question because it does not show how to extract nested data into a std::map. Moreover, when I try to use this code I get "poco\include\poco\dynamic\var.h(199): error C2664: 'void Poco::Dynamic::VarHolder::convert(Poco::UTF16String &) const' : cannot convert argument 1 from 'Poco::JSON::Object' to 'Poco::Int8 &'" – Bungles May 17 '15 at 20:59
0

Here's what worked:

// 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();
}

It would appear DynamicStruct cannot be used for nested fields.

Bungles
  • 1,969
  • 2
  • 25
  • 54
  • See [http://stackoverflow.com/questions/30248751/how-to-create-and-parse-hierarchical-nested-json-with-poco-c#comment48685290_30292859] – Christian Severin Nov 04 '15 at 11:56