【问题标题】:Poco C++ building nested JSON objectsPoco C++ 构建嵌套的 JSON 对象
【发布时间】:2015-05-09 03:44:11
【问题描述】:

我有一个嵌套的 JSON 对象。我试图在一个函数中构建它并将内部对象添加到原始对象中,但我无法提取结果。

void build_object (Poco::JSON::Object * const result)
{

    /* Construct some int/bool/string fields here */

    Poco::JSON::Object inner;
    inner.set("some_number", 5);
    inner.set("some_string", "xyz");

    /* This is where it breaks down */ 
    std::string key = "new_object";
    result->set("new_object", inner);

    /* Then some debugging and testing */
    // The new object is printed inside the first -> seems like it's working
    result->stringify(std::cout); 

    printf("result has(key): %i\n", result->has(key)); // true
    printf("isObject: %i\n", result->isObject(key));   // false - huh?
    printf("isNull: %i\n", result->isNull(key));       // false
    printf("isArray: %i\n", result->isArray(key));     // false

    Poco::JSON::Object::Ptr ptr = result->getObject(key); 
    // unsurpisingly fails since the above indicates it's not an object
    printf("ptr isNull: %i\n", ptr.isNull());          // true
    // ptr->has("some_number"); // throws NullPointerException

    // if it's not an object/null/array, it must be a value
    Poco::Dynamic::Var v = result->get(key);
    // at least one of these things should be true, otherwise what is it?
    printf("var isString: %i\n", v.isString());  // false
    printf("var isStuct: %i\n", v.isStruct());   // false
    printf("var isEmpty: %i\n", v.isEmpty());    // false
    printf("var isArray: %i\n", v.isArray());    // false
    printf("var isSigned: %i\n", v.isSigned());  // false
    printf("var isNumeric: %i\n", v.isNumeric());// false
}

所以,我有一个正确放入结果的内部对象,它正在通过 stringify 打印所有正确的值,并且 result->has() 是成功的。但是,根据结果,它不是对象、数组或null,所以你应该可以用var获取它。但是,一旦从 var 中获取,它就不是字符串、结构、数组或数字,也不是空的。内在对象似乎同时存在和不存在。

那么,如何将这个对象放入我的结果中?以及如何取出?

谢谢

注意:我看过这个线程Correct usage of Poco C++ JSON for parsing data,但它是从字符串构建 JSON 对象,然后对其进行解析。我想我可以将所有内容构建为字符串并在最后一步转换为 Poco 对象,但我仍然很好奇为什么会发生上述情况。此外,使用 result->set() 和 result->get() 是一种比通过字符串更简洁、更少 hack-y 的解决方案。

参考:Poco JSON Doc, Poco Dynamic Var Doc

【问题讨论】:

  • result->hasresult->isObject等的返回类型是什么?如果是bool,那么在printf() 语句中使用bool 是未定义的行为,因为bool 没有官方格式说明符。
  • 返回类型是布尔值。我在上面的 cmets 中用 true 和 false 代替了 1 和 0。这不是打印问题 - 我可以将它们全部转换为 int 并获得相同的结果,也可以作为更确凿的空对象测试,尝试使用来自 ptr=result->getObject(key) 的 ptr 会引发空指针异常

标签: c++ json poco-libraries


【解决方案1】:

默认情况下,Poco::JSON 对象和数组在内部作为共享指针保存(优化以避免值复制)并且一切都是 Dynamic::Var,因此它适用于指针和值。当您将 Object 作为值插入时,它会起作用,因为 Dynamic::Var 几乎可以保存任何东西,但是您在检查它时遇到的问题来自这样一个事实,即内部比较不会为 Object 值返回 true,因为它仅与默认类型进行比较 - Poco::SharedPtr<:json::object>.

这里有一个解决方法:

void build_object (Poco::JSON::Object * const result)
{
    // smart pointer, so don't worry about cleaning up
    Poco::JSON::Object::Ptr inner = new Poco::JSON::Object;
    inner->set("some_number", 5);
    inner->set("some_string", "xyz");

    std::string key = "new_object";
    result->set(key, inner);
    printf("isObject: %i\n", result->isObject(key)); // true
}

我已经打开了github issue 来缓解这个警告。

【讨论】:

    【解决方案2】:

    我一直在尝试使用 poco 库创建具有嵌套对象的 json 文件。终于可以使用 Poco::Json::Array 了。

    请找到发布的代码snippet。希望它会有所帮助。附有帖子的 Json 输出。

    #include "Poco\JSON\JSON.h"
    #include "Poco\JSON\Stringifier.h"
    #include "Poco\JSON\Object.h"
    #include "Poco\Dynamic\Var.h"
    
    
    using namespace std;
    using Poco::JSON::Stringifier;
    using Poco::JSON::Object;
    using Poco::JSON::Array;
    
            void makeJsonNestedObject()
        {
            Object RootObj(true);
            Array FLArray;
    
            for(int i=0; i<3; i++)
            {       
                Object::Ptr FirstLevelArrayNode = new Poco::JSON::Object(true);
                TCHAR strNameBuff[15];
                _stprintf(strNameBuff, _T("%s_%d"),_T("Servername"),i);
                std::basic_string<TCHAR> strName = strNameBuff;
    
    
                FirstLevelArrayNode->set("HostName", strName);
                FirstLevelArrayNode->set("Overall Impact", "Dummy Data");
    
                Array SLArray;
    
                for(int j=0; j<3;j++)
                {
                    Object::Ptr SecondLevelArrayNode = new Poco::JSON::Object(true);
                    TCHAR attr1NameBuff[15];
                    TCHAR attr2NameBuff[15];
                    _stprintf(attr1NameBuff, _T("%s_%d"),_T("AttrOne"),j);
                    _stprintf(attr2NameBuff, _T("%s_%d"),_T("AttrTwo"),j);
                    std::basic_string<TCHAR> attr1Name = attr1NameBuff;
                    std::basic_string<TCHAR> attr2Name = attr2NameBuff;
                    SecondLevelArrayNode->set("Attribute", attr1Name);
                    SecondLevelArrayNode->set("SubAttribute", attr2Name);
                    Poco::Dynamic::Var obj(SecondLevelArrayNode);
                    SLArray.add(obj);
                }   
                FirstLevelArrayNode->set("Attribute_Details",SLArray);
                Poco::Dynamic::Var FLArrayNodeobj(FirstLevelArrayNode);
                FLArray.add(FLArrayNodeobj);
    
            }
            std::ostringstream os;
            std::cout <<"before stringlify.." << std::endl;
            FLArray.stringify(os, 2);
            std::cout << os.str() << std::endl;
    
        }
    

    Json 输出:

        [
      {
        "HostName" : "Servername_0",
        "Overall Impact" : "Dummy Data",
        "Attribute_Details" : [
          {
            "Attribute" : "AttrOne_0",
            "SubAttribute" : "AttrTwo_0"
          },
          {
            "Attribute" : "AttrOne_1",
            "SubAttribute" : "AttrTwo_1"
          },
          {
            "Attribute" : "AttrOne_2",
            "SubAttribute" : "AttrTwo_2"
          }
        ]
      },
      {
        "HostName" : "Servername_1",
        "Overall Impact" : "Dummy Data",
        "Attribute_Details" : [
          {
            "Attribute" : "AttrOne_0",
            "SubAttribute" : "AttrTwo_0"
          },
          {
            "Attribute" : "AttrOne_1",
            "SubAttribute" : "AttrTwo_1"
          },
          {
            "Attribute" : "AttrOne_2",
            "SubAttribute" : "AttrTwo_2"
          }
        ]
      },
      {
        "HostName" : "Servername_2",
        "Overall Impact" : "Dummy Data",
        "Attribute_Details" : [
          {
            "Attribute" : "AttrOne_0",
            "SubAttribute" : "AttrTwo_0"
          },
          {
            "Attribute" : "AttrOne_1",
            "SubAttribute" : "AttrTwo_1"
          },
          {
            "Attribute" : "AttrOne_2",
            "SubAttribute" : "AttrTwo_2"
          }
        ]
      }
    ]
    

    【讨论】:

      猜你喜欢
      • 2023-03-21
      • 2013-03-15
      • 1970-01-01
      • 2011-12-09
      • 1970-01-01
      • 2017-02-14
      • 2017-12-22
      • 1970-01-01
      • 2021-10-02
      相关资源
      最近更新 更多