Reputation: 33
I have a json structure loaded on to a hash, like this:
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,
},
],
},
};
Tools like JSON::Path, return the values of the elements matching the path.
my $jpath = JSON::Path->new('$.*.book[*]');
my @books = $jpath->values($data);
I would like to get the Paths, not the values. Something like:
[
'$->{store}{book}[0]',
'$->{store}{book}[1]',
'$->{store}{book}[2]'
]
I want to find information in the Path, in order to know the location of the results and not the results themselves. For example, given the query:
my $jpath = JSON::Path->new('$.*.book[*]');
I would like to know if the Path contains "store1" or "store2", so I need the query to return the Paths.
Is there a way to do this?
Thanx, Spiros
Upvotes: 3
Views: 298
Reputation: 118158
You should be able to use 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;
Output:
$['store']['book']['0']
$['store']['book']['1']
$['store']['book']['2']
$['store']['book']['3']
Now, in this case, you seem to want to have a list of stores with out using a data structure appropriate for storing lists. That is, it would be more appropriate to have:
my $data = {
stores => [
# each store is product type to list of
# products of that type in that store
]
};
Each store should probably also have a name property.
I am assuming in real life you are not emulating arrays with integer suffixes in the name. In that case, the top level keys can be arbitrary strings. So, using the $data
structure you provided,
# All books in all stores
my $jpath = JSON::Path->new('$.*.book[*]');
my @books = $jpath->paths($data);
say for @books;
Output:
$['store1']['book']['0']
$['store1']['book']['1']
$['store2']['book']['0']
$['store2']['book']['1']
Upvotes: 3