我正在尝试通过加载两个json文件来构建Document。最后加载的文件具有最高优先级。
在下面的示例中,来自item1.value1
的{{1}}会覆盖file B
的值。 file A
中不存在item1.value2
item2
,因此最终文档仅从file A
获取值
文件A:
file B
文件B:
{
level1: {
level2: {
item1: {
value1: 20,
}
}
}
我的目标:
{
level1: {
item2{
value1: 50
value2: 60,
}
level2: {
item1:{
value1: 40
value2: 30,
}
}
}
当我使用范围迭代文档时,另一个问题是迭代{
level1: {
item2{
value1: 50
value2: 60,
}
level2: {
item1: {
value1: 40,
value2: 30,
}
}
}
成员,我怎样才能浏览整个DOM?
level1
答案 0 :(得分:0)
我想你会尝试这个(适合我):
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模型(如上所述)。
希望它有所帮助。
答案 1 :(得分:0)
以上实现假定srcObject
和dstObject
共享相同的内存,因为它传递原始值而不是复制原始值。
这意味着dstObject
将在释放srcObject
时保留释放的对象。
我通过复制值来实现它:
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 ;
}