我有一个JSON格式的配置文件,需要加载到Perl中,然后从另一个JSON文件中加载新设置并部分覆盖/扩展。可能添加/更改的特定设置因情况而异,因此我希望使此覆盖尽可能灵活。
我的计划是将新的部分配置合并到现有的完整配置对象中-可以是JSON格式的,也可以是使用decode_json后的Perl嵌套数据结构。这个转换很好用。
在Perl中有没有简单高效的方法来做到这一点,而不是递归遍历复杂的数据结构并进行大量特定比较?我已经研究了Hash::Merge,但它正在破坏我的数据。问题似乎是它查看高级键/值对(下面的“config”或“bookToolbar”)并覆盖该高级别上的完整键/值对。我想要的是深度优先搜索并覆盖它能找到的最具体的值,同时保留原始的其他键/值对。
例如,这是一个“完整”的配置:
我的计划是将新的部分配置合并到现有的完整配置对象中-可以是JSON格式的,也可以是使用decode_json后的Perl嵌套数据结构。这个转换很好用。
在Perl中有没有简单高效的方法来做到这一点,而不是递归遍历复杂的数据结构并进行大量特定比较?我已经研究了Hash::Merge,但它正在破坏我的数据。问题似乎是它查看高级键/值对(下面的“config”或“bookToolbar”)并覆盖该高级别上的完整键/值对。我想要的是深度优先搜索并覆盖它能找到的最具体的值,同时保留原始的其他键/值对。
例如,这是一个“完整”的配置:
{
"config" : {
"bookToolbar" : {
"highlights" : {
"enabled" : false
},
"bookmark" : {
"enabled" : false
}
},
"pageAspectRatio" : {
"width" : "432",
"height" : "648"
},
"highlighter" : {
"sharedColor" : "#000000",
"colors" : [
"#ffff00"
]
}
"mainMenu" : {
"index" : {
"dataPath" : "data/index/",
"enabled" : false
},
"media" : {
"dataPath" : "data/media.xml",
"enabled" : false
},
"toc" : {
"dataPath" : "data/toc.xml"
},
"glossary" : {
"audioPath" : "audio/glossary/",
"dataPath" : "data/glossary.xml",
"imagePath" : "img/glossary/",
"enabled" : false
}
}
},
"pagelist" : [{
"hasOnPageNotes" : true,
"pageName" : "cover",
"hasScreenReader" : false,
"hasTextMarkup" : true,
"hasLinks" : false,
"pageId" : "cover"
}, {
"hasOnPageNotes" : true,
"pageName" : "1",
"hasScreenReader" : false,
"hasTextMarkup" : true,
"hasLinks" : false,
"pageId" : "1"
}
]
}
以下是我想要用来部分覆盖/扩展上述内容的数据:
{
"config" : {
"bookToolbar" : {
"bookmark" : {
"enabled" : true
},
"help" : {
"data" : {
"url" : "aGreatHelpFile.html"
},
"enabled" : true
},
"links" : {
"enabled" : true
}
}
},
"pagelist" : [{
"hasOnPageNotes" : true,
"pageName" : "2",
"hasScreenReader" : false,
"hasTextMarkup" : true,
"hasLinks" : false,
"pageId" : "2"
}
]
}
我的期望输出是:
{
"config" : {
"bookToolbar" : {
"highlights" : {
"enabled" : false
},
"help" : {
"data" : {
"url" : "aGreatHelpFile.html"
},
"enabled" : true
},
"bookmark" : {
"enabled" : true
}
"links" : {
"enabled" : false
}
},
"pageAspectRatio" : {
"width" : "432",
"height" : "648"
},
"highlighter" : {
"sharedColor" : "#000000",
"colors" : [
"#ffff00"
]
},
"mainMenu" : {
"index" : {
"dataPath" : "data/index/",
"enabled" : false
},
"media" : {
"dataPath" : "data/media.xml",
"enabled" : false
},
"toc" : {
"dataPath" : "data/toc.xml"
},
"glossary" : {
"audioPath" : "audio/glossary/",
"dataPath" : "data/glossary.xml",
"imagePath" : "img/glossary/",
"enabled" : false
}
}
},
"pagelist" : [{
"hasOnPageNotes" : true,
"pageName" : "cover",
"hasScreenReader" : false,
"hasTextMarkup" : true,
"hasLinks" : false,
"pageId" : "cover"
}, {
"hasOnPageNotes" : true,
"pageName" : "1",
"hasScreenReader" : false,
"hasTextMarkup" : true,
"hasLinks" : false,
"pageId" : "1"
}, {
"hasOnPageNotes" : true,
"pageName" : "2",
"hasScreenReader" : false,
"hasTextMarkup" : true,
"hasLinks" : false,
"pageId" : "2"
}
]
}
RIGHT_PRECEDENT
进行合并,看起来得到了你想要的结果。Hash::Merge 的文档提到在 Windows 上运行 ActiveState Perl 或旧版本的 Clone 模块时可能会出现一些问题。这两个问题可能会影响你吗? - rutterRIGHT_PRECEDENT
但没有成功,但它听起来确实是我想要的。我确实在Windows上使用ActiveState发行版,所以可能是问题所在...让我在我的Mac上尝试一下,看看是否有所改善。 - uptownnickbrownHash::Merge
和RIGHT_PRECEDENT
完美地工作了...在更新 Clone 到最新版本(Clone-0.34)后,它也在 Windows 上运行!感谢您重新审视该行为选项的提示。 - uptownnickbrown