【问题标题】:How to create and parse hierarchical/nested JSON with Poco C++?如何使用 Poco C++ 创建和解析分层/嵌套 JSON?
【发布时间】:2015-05-14 22:49:57
【问题描述】:

经过编辑以简化并显示我的 EXACT 代码。

我有以下数据需要序列化为 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();
    }
}

【问题讨论】:

    标签: json c++11 poco-libraries


    【解决方案1】:

    更新:在整理这个例子时,我发现了a subtle bug;它已在即将发布的 1.6.1 和 1.7.0 版本的存储库中修复。下面的示例适用于早期版本,只是不要对 JSON::Stringifier::stringify() 使用保留顺序(使用 Object::stringify() 很好)。

    给你;如果您不关心保留 JSON 条目的插入顺序,请不要将任何内容传递给 Object 构造函数 - 它的性能会稍好一些:

    #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;
    }
    

    【讨论】:

    • 修改问题以显示准确的代码。我要做的就是得到如图所示的“metaName”和“metaValue”。
    • 您不断更改问题,但答案在发布的代码中。我已对其进行了更新以准确显示如何 (1) 以编程方式创建 json 数据结构,(2) 将其序列化为 std::string,(3) 将 std::string 解析回数据结构和 (4) 遍历整个结构,检测其中的嵌套 JSON 对象。研究这个例子,你就会明白怎么做。
    • 我一直在重申这个问题,因为你一直没有回答。你的代码在我的电脑上不起作用,所以我唯一能(并且做过)的另一件事就是发布我的代码并让你指出哪里出了问题。你的代码对我没有任何意义,因为它没有做我想做的事情。
    • 那我帮不了你了,对不起。我在此处发布的代码可以正常工作并且可以满足您的要求。祝你旅途愉快。
    • 不,抱歉。我建议您阅读提出的原始问题,然后研究我给您的代码。它可以正常工作并且可以满足您的要求。
    【解决方案2】:

    以下是有效的:

    // 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 似乎不能用于嵌套字段。

    【讨论】:

    • 当然可以(并且此评论只是为了防止传播错误信息):DynamicStruct nestedStruct = jsonStruct["metadata"].extract&lt;DynamicStruct&gt;();
    • 看,现在不是那么难了吧?
    猜你喜欢
    • 1970-01-01
    • 2021-10-05
    • 1970-01-01
    • 2015-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-12
    相关资源
    最近更新 更多