在Perl中,如何查询JSON::Path对象并返回匹配元素的路径?



我有一个json结构加载到散列中,如下所示:

my $data = {
"store1" => {
"book" => [ 
{ "category" =>  "reference",
"author"   =>  "Nigel Rees",
"title"    =>  "Sayings of the Century",
"price"    =>  8.95,
},
{ "category" =>  "fiction",
"author"   =>  "Herman Melville",
"title"    =>  "Moby Dick",
"isbn"     =>  "0-553-21311-3",
"price"    =>  8.99,
},
],
"bicycle" => [
{ "color" => "red",
"price" => 19.95,
},
],
},
"store2" => {
"book" => [ 
{ "category" =>  "reference",
"author"   =>  "Nigel Rees",
"title"    =>  "Sayings of the Century",
"price"    =>  8.95,
},
{ "category" =>  "fiction",
"author"   =>  "Herman Melville",
"title"    =>  "Moby Dick",
"isbn"     =>  "0-553-21311-3",
"price"    =>  8.99,
},
],
"bicycle" => [
{ "color" => "red",
"price" => 19.95,
},
],
},
};

像JSON::Path这样的工具,返回与路径匹配的元素值。

my $jpath   = JSON::Path->new('$.*.book[*]');
my @books   = $jpath->values($data);

我想要得到路径,而不是值。比如:

[
'$->{store}{book}[0]',
'$->{store}{book}[1]',
'$->{store}{book}[2]'
]

我想在路径中查找信息,以便知道结果的位置而不是结果本身。例如,给定查询:

my $jpath   = JSON::Path->new('$.*.book[*]');

我想知道路径是否包含"store1"或"store2",所以我需要查询返回路径。

有办法做到这一点吗?

谢谢,斯皮罗

您应该能够使用paths

#!/usr/bin/env perl
use strict;
use warnings;
use feature 'say';
my $data = {
"store" => {
"book" => [ 
{ "category" =>  "reference",
"author"   =>  "Nigel Rees",
"title"    =>  "Sayings of the Century",
"price"    =>  8.95,
},
{ "category" =>  "fiction",
"author"   =>  "Evelyn Waugh",
"title"    =>  "Sword of Honour",
"price"    =>  12.99,
},
{ "category" =>  "fiction",
"author"   =>  "Herman Melville",
"title"    =>  "Moby Dick",
"isbn"     =>  "0-553-21311-3",
"price"    =>  8.99,
},
{ "category" =>  "fiction",
"author"   =>  "J. R. R. Tolkien",
"title"    =>  "The Lord of the Rings",
"isbn"     =>  "0-395-19395-8",
"price"    =>  22.99,
},
],
"bicycle" => [
{ "color" => "red",
"price" => 19.95,
},
],
},
};

# All books in the store
my $jpath   = JSON::Path->new('$.store.book[*]');
my @books   = $jpath->paths($data);
say for @books;

输出:

$['store']['book']['0']
$['store']['book']['1']
$['store']['book']['2']
$['store']['book']['3']

现在,在这种情况下,您似乎想要有一个存储列表,而不使用适合存储列表的数据结构。也就是说,更合适的是:

my $data = {
stores => [
# each store is product type to list of
# products of that type in that store
]
};

每个store可能也应该有一个name属性。

我假设在现实生活中您没有模拟名称中带有整数后缀的数组。在这种情况下,顶级键可以是任意字符串。因此,使用您提供的$data结构,

# All books in all stores
my $jpath   = JSON::Path->new('$.*.book[*]');
my @books   = $jpath->paths($data);
say for @books;

输出:

$['store1']['book']['0']
$['store1']['book']['1']
$['store2']['book']['0']
$['store2']['book']['1']

最新更新