簡體   English   中英

如何使用rapidjson合並兩個json文件

[英]How to merge two json file using rapidjson

我正在嘗試通過加載兩個json文件來構建文檔。 最后加載的文件具有最高優先級。 在下面的示例中, file B中的item1.value1覆蓋了file A的值。 item1.value2 item2file A中不存在,因此最終文檔僅從file B文件A中獲取值:

{
level1: {
      level2: {
               item1: {
                       value1: 20,
                      }
              }
}

文件B:

{
   level1: {
         item2{
               value1: 50
               value2: 60,        
               }
       level2: {
            item1:{
                       value1: 40
                       value2: 30,
       }
  }
}

我的目標:

{
   level1: {
      item2{
            value1: 50
            value2: 60,        
      }
       level2: {
            item1: {
                       value1: 40,
                       value2: 30,
       }
  }
}

當我使用范圍來遍歷Document時,另一個問題是,僅對level1成員進行了遍歷,如何遍歷整個DOM?

for (auto& m : document.GetObject())
    printf("Type of member %s is %s\n",
        m.name.GetString(), kTypeNames[m.value.GetType()]);

我想您可以嘗試一下(對我有用):

void mergeObjects(rapidjson::Value &dstObject, rapidjson::Value &srcObject, rapidjson::Document::AllocatorType &allocator)
{
    for (auto srcIt = srcObject.MemberBegin(); srcIt != srcObject.MemberEnd(); ++srcIt)
    {
        auto dstIt = dstObject.FindMember(srcIt->name);
        if (dstIt != dstObject.MemberEnd())
        {
            assert(srcIt->value.GetType() == dstIt->value.GetType());
            if (srcIt->value.IsArray())
            {
                for (auto arrayIt = srcIt->value.Begin(); arrayIt != srcIt->value.End(); ++arrayIt)
                {
                    dstIt->value.PushBack(*arrayIt, allocator);
                }
            }
            else if (srcIt->value.IsObject())
            {
                mergeObjects(dstIt->value, srcIt->value, allocator);
            }
            else
            {
                dstIt->value = srcIt->value;
            }
        }
        else
        {
            dstObject.AddMember(srcIt->name, srcIt->value, allocator);
        }
    }
}
//...
rapidjson::Document from;
rapidjson::Document to;
mergeObjects(to, from, to.GetAllocator());

注意,節點類型必須相等。 它還通過串聯而不是替換來合並數組。

您可以使用遞歸遍歷整個DOM模型(如上所述)。

希望能幫助到你。

上面的實現假定srcObjectdstObject共享相同的內存,因為它傳遞原始值而不是復制它們。 這意味着當釋放srcObject時, dstObject將保存釋放的對象。

我通過復制值來實現它:

bool mergeObjects(rapidjson::Value &dstObject, rapidjson::Value &srcObject, rapidjson::Document::AllocatorType &allocator)
{
    for (auto srcIt = srcObject.MemberBegin(); srcIt != srcObject.MemberEnd(); ++srcIt)
    {
        auto dstIt = dstObject.FindMember(srcIt->name);
        if (dstIt == dstObject.MemberEnd())
        {
            rapidjson::Value dstName ;
            dstName.CopyFrom(srcIt->name, allocator);
            rapidjson::Value dstVal ;
            dstVal.CopyFrom(srcIt->value, allocator) ;

            dstObject.AddMember(dstName, dstVal, allocator);

            dstName.CopyFrom(srcIt->name, allocator);
            dstIt = dstObject.FindMember(dstName);
            if (dstIt == dstObject.MemberEnd())
                return false ;
        }
        else
        {
            auto srcT = srcIt->value.GetType() ;
            auto dstT = dstIt->value.GetType() ;
            if(srcT != dstT)
                return false ;

            if (srcIt->value.IsArray())
            {
                for (auto arrayIt = srcIt->value.Begin(); arrayIt != srcIt->value.End(); ++arrayIt)
                {
                    rapidjson::Value dstVal ;
                    dstVal.CopyFrom(*arrayIt, allocator) ;
                    dstIt->value.PushBack(dstVal, allocator);
                }
            }
            else if (srcIt->value.IsObject())
            {
                if(!mergeObjects(dstIt->value, srcIt->value, allocator))
                    return false ;
            }
            else
            {
                dstIt->value.CopyFrom(srcIt->value, allocator) ;
            }
        }
    }

    return true ;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM