gpt4 book ai didi

json - 如何在 Perl 中合并两个复杂的数据结构?

转载 作者:行者123 更新时间:2023-12-04 02:48:24 24 4
gpt4 key购买 nike

我有一个格式为 JSON 的配置文件,我需要将其加载到 Perl 中,然后使用从单独的 JSON 文件加载的新设置部分覆盖/扩展。可能添加/更改的特定设置各不相同,因此我希望尽可能灵活地设置此覆盖。

我的计划是在使用 decode_json 后将新的部分配置合并到现有的完整配置对象中 - 在 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"
}
]
}

最佳答案

事实证明,Hash::Merge 只是使用过时版本的克隆模块在 Windows 上破坏了我的数据。

使用最新版本(或在我的 Mac 上立即使用),以下代码完全满足我的需要:

#!/usr/bin/env perl -w
use strict;
use JSON;
use Hash::Merge qw( merge );
Hash::Merge::set_behavior('RIGHT_PRECEDENT');

# Load full config into hashref
open (IN, "<:utf8", "full-config.txt");
my $app_data;
while(<IN>) {$app_data .= $_;}
my $app_json = decode_json($app_data);
close IN;

# Sample portion of config options to override/extend
my $app_override = '{"config": {
"bookToolbar": {
"bookmark": {
"enabled":false
}, "help": {
"data": {
"url":"aGreatHelpFile.html"
}, "enabled":true
}, "closeBook": {
"enabled":true
}
}
},
"pagelist":[
{
"hasOnPageNotes" : true,
"pageName" : "25",
"hasTextMarkup" : true,
"hasScreenReader" : false,
"hasLinks" : false,
"pageId" : "0025"
}
]
}';
my $app_override_hash = from_json($app_override, {utf8 => 1});

# Merge with right precedent, $app_json hash ref has everything we need.
$app_json = merge( $app_json, $app_override_hash );

我发现此表对分析 Hash::Merge 中的不同优先级选项特别有用(这是 straight from the docs:

    LEFT TYPE   RIGHT TYPE      LEFT_PRECEDENT       RIGHT_PRECEDENT
SCALAR SCALAR $a $b
SCALAR ARRAY $a ( $a, @$b )
SCALAR HASH $a %$b
ARRAY SCALAR ( @$a, $b ) $b
ARRAY ARRAY ( @$a, @$b ) ( @$a, @$b )
ARRAY HASH ( @$a, values %$b ) %$b
HASH SCALAR %$a $b
HASH ARRAY %$a ( values %$a, @$b )
HASH HASH merge( %$a, %$b ) merge( %$a, %$b )

LEFT TYPE RIGHT TYPE STORAGE_PRECEDENT RETAINMENT_PRECEDENT
SCALAR SCALAR $a ( $a ,$b )
SCALAR ARRAY ( $a, @$b ) ( $a, @$b )
SCALAR HASH %$b merge( hashify( $a ), %$b )
ARRAY SCALAR ( @$a, $b ) ( @$a, $b )
ARRAY ARRAY ( @$a, @$b ) ( @$a, @$b )
ARRAY HASH %$b merge( hashify( @$a ), %$b )
HASH SCALAR %$a merge( %$a, hashify( $b ) )
HASH ARRAY %$a merge( %$a, hashify( @$b ) )
HASH HASH merge( %$a, %$b ) merge( %$a, %$b )

关于json - 如何在 Perl 中合并两个复杂的数据结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18341444/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com