How to create and parse hierarchical/nested JSON with Poco C++?
UPDATE: while putting together this example, I found a subtle bug; it is fixed in the repo for upcoming 1.6.1 and 1.7.0 release. The sample below works fine with earlier releases, just don't use preserve order with JSON::Stringifier::stringify() (using Object::stringify() is fine).
Here you go; if you don't care about preserving JSON entries insertion order, don't pass anything to Object constructor - it will perform slightly better:
#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;}
Here's what worked:
// Deserialize from JSONvoid 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.