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

In Perl, how can query a JSON::Path object and return the paths of the matched elements?

我有一个 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 这样的工具,return 匹配路径的元素的值。

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”,所以我需要查询 return 路径。

有办法吗?

谢谢, 斯皮罗斯

您应该可以使用 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
  ]
};

每个商店应该也有一个名称 属性。

我假设在现实生活中你不是 emulating arrays with integer suffixes in the 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']