gpt4 book ai didi

json - 如何递归搜索与给定模式匹配的所有节点的 JSON 文件并将 JSON 'path' 返回到节点及其值?

转载 作者:行者123 更新时间:2023-12-03 18:30:28 25 4
gpt4 key购买 nike

假设我有 this文本文件中的 JSON:

{"widget": {
"debug": "on",
"window": {
"title": "Sample Konfabulator Widget",
"name": "main_window",
"width": 500,
"height": 500
},
"image": {
"src": "Images/Sun.png",
"name": "sun1",
"hOffset": 250,
"vOffset": 250,
"alignment": "center"
},
"text": {
"data": "Click Here",
"size": 36,
"style": "bold",
"name": "text1",
"hOffset": 250,
"vOffset": 100,
"alignment": "center",
"onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
}
}}
使用 Perl,我已将文件读入一个名为 $json_obj 的 JSON 对象。使用 JSON::XS。
如何搜索 $json_obj对于名为 name 的所有节点并返回/打印以下内容作为结果/输出:
widget->window->name: main_window
widget->image->name: sun1
widget->text->name: text1
笔记:
  • 与搜索词匹配的节点名称可以出现在树的任何级别
  • 搜索词可以是纯文本或正则表达式
  • 我希望能够提供我自己的分支分隔符来覆盖默认值,例如 ->
  • 示例 / (为简单起见,我将把它放在 perl $variable 中)

  • 我希望能够在我的搜索中指定多个节点级别,以便指定 path匹配,例如:指定 id/colour将返回包含名为 id 的节点的所有路径这也是一个父节点,其子节点名为 colour
  • 在结果值周围显示双引号是可选的
  • 我希望能够搜索多种模式,例如/(name|alignment)/对于“查找所有名为 namealignment
  • 的节点

    在上面最后一个注释中显示搜索结果的示例:
    widget->window->name: main_window
    widget->image->name: sun1
    widget->image->alignment: center
    widget->text->name: text1
    widget->text->alignment: center
    由于 JSON 主要只是文本,我还不确定使用 JSON::XS 的好处,所以欢迎任何关于为什么这是更好或更坏的建议。
    不用说它需要递归才能搜索 n任意级别的深度。
    这是我到目前为止所拥有的,但我只是其中的一部分:
    #!/usr/bin/perl

    use 5.14.0;
    use warnings;
    use strict;
    use IO::File;
    use JSON::XS;

    my $jsonfile = '/home/usr/filename.json';
    my $jsonpath = 'image/src'; # example search path
    my $pathsep = '/'; # for displaying results

    my $fh = IO::File->new("$jsonfile", "r");
    my $jsontext = join('',$fh->getlines());
    $fh->close();

    my $jsonobj = JSON::XS->new->utf8->pretty;

    if (defined $jsonpath) {
    my $perltext = $jsonobj->decode($jsontext); # is this correct?
    recurse_tree($perltext);
    } else {
    # print file to STDOUT
    say $jsontext;
    }

    sub recurse_tree {
    my $hash = shift @_;
    foreach my $key (sort keys %{$hash}) {
    if ($key eq $jsonpath) {
    say "$key = %{$hash}{$key} \n"; # example output
    }
    if (ref $hash->{$key} eq 'HASH' ||
    ref $hash->{$key} eq 'ARRAY') {
    recurse_tree($hash->{$key});
    }
    }
    }

    exit;
    上述脚本的预期结果将是:
    widget/image/src: Images/Sun.png

    最佳答案

    一旦 JSON 被解码,就会有一个复杂的(嵌套的)Perl 数据结构供您搜索,而您展示的代码正是针对该结构的。
    但是,有一些图书馆可以提供帮助;要么完全完成这项工作,要么提供完整的、工作的和经过测试的代码,您可以根据具体需求进行微调。
    模块Data::Leaf::Walker似乎合适。一个简单的例子

    use warnings;
    use strict;
    use feature 'say';

    use Data::Dump qw(dd);
    use JSON;
    use List::Util qw(any);

    use Data::Leaf::Walker;

    my $file = shift // 'data.json'; # provided data sample

    my $json_data = do { local (@ARGV, $/) = $file; <> }; # read into a string
    chomp $json_data;

    my $ds = decode_json $json_data;
    dd $ds; say ''; # show decoded data

    my $walker = Data::Leaf::Walker->new($ds);

    my $sep = '->';
    while ( my ($key_path, $value) = $walker->each ) {
    my @keys_in_path = @$key_path;
    if (any { $_ eq 'name' } @keys_in_path) { # selection criteria
    say join($sep, @keys_in_path), " => $value"
    }
    }
    这个“walker”遍历数据结构,保留每个叶子的键列表。这就是使该模块特别适合您的任务的原因,并且与许多其他模块相比,其目的简单。请参阅文档。
    以上打印,用于问题中提供的示例数据
    小部件->窗口->名称 => main_window
    小部件->文本->名称=> text1
    小部件->图像->名称 => sun1

    在上面的代码中选择键路径的标准的实现相当简单,因为它检查 'name'路径中的任何位置,一次,然后打印整个路径。虽然问题没有指定如何处理路径中较早的匹配项或多个匹配项,但这可以调整,因为我们始终拥有完整路径。
    您的愿望 list 的其余部分也很容易实现。细读 List::UtilList::MoreUtils寻求阵列分析的帮助。
    Data::Traverse 是另一个模块,它是满足可能的特定需求的一个很好的起点。 .特别简单,在 70-odd lines of code ,所以很容易定制。

    关于json - 如何递归搜索与给定模式匹配的所有节点的 JSON 文件并将 JSON 'path' 返回到节点及其值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66287984/

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