Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to merge two json file using rapidjson

I am trying to build a Document by loading two json files. The file loaded last takes the highest priority. In the example below item1.value1 from file B overwrites the value from file A. item1.value2 item2 does not exist in file A so the final Document just takes values from file B file A:

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

file B:

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

my goal:

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

Another question when I am using the range for to iterate through the Document, only level1 members are iterated, how can I go through the entire DOM?

for (auto& m : document.GetObject())
    printf("Type of member %s is %s\n",
        m.name.GetString(), kTypeNames[m.value.GetType()]);
like image 259
Frank Liu Avatar asked Oct 28 '25 08:10

Frank Liu


1 Answers

The above implementation assume that srcObject and dstObject share the same memory because it passes the original values instead of copying them. This means that dstObject will hold freed objects when srcObject is freed.

I've implemented it by copying the values:

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 ;
}
like image 98
nadavi Avatar answered Oct 31 '25 00:10

nadavi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!