use Test::Most;
use Test::Deep;
use JSON::MaybeXS qw/encode_json decode_json/;
use JSON::Path::Evaluator;
use Storable qw(dclone);
use Tie::IxHash;
my $json = sample_json();
my %data = %{ decode_json($json) };
subtest filter => sub {
my @expressions = (
'$..[?(@.price > 10)]' => [ grep { $_->{price} > 10 } @{ $data{store}{book} } ],
'$.complex_array[?(@.weight > 10)]' =>
[ map { dclone $_ } grep { $_->{weight} > 10 } @{ $data{complex_array} } ],
'$.complex_array[?($_->{weight} > 10)]' =>
[ map { dclone $_ } grep { $_->{weight} > 10 } @{ $data{complex_array} } ],
'$.complex_array[?(@.type.code=="CODE_ALPHA")]' =>
[ dclone( ( grep { $_->{type}{code} eq 'CODE_ALPHA' } @{ $data{complex_array} } )[0] ) ],
'$.complex_array[?(@.weight > 10)].classification.quux' =>
[ map { $_->{classification}{quux} } grep { $_->{weight} > 10 } @{ $data{complex_array} } ],
'$.complex_array[?(@.quux)]' => [ grep { $_->{quux} } @{ $data{complex_array} } ],
);
do_test(@expressions);
};
subtest simple => sub {
my @expressions = (
'$.nonexistent' => [ ],
'$.simple' => [ $data{simple} ],
'$.long_hash.key1.subkey2' => [ $data{long_hash}{key1}{subkey2} ],
'$.long_hash.key1' => [ dclone $data{long_hash}{key1} ],
q{$.complex_array[0]['foo']} => [ $data{complex_array}[0]{foo} ],
'$.multilevel_array.1.0.0' => [ $data{multilevel_array}->[1][0][0] ],
'$.multilevel_array.0.1[0]' => [ $data{multilevel_array}->[0][1][0] ],
'$.multilevel_array[0][0][1]' => [ $data{multilevel_array}->[0][0][1] ],
'$.store.book[0].title' => [ $data{store}{book}->[0]{title} ],
'$.array[0]' => [ $data{array}->[0] ],
);
do_test(@expressions);
};
subtest all => sub {
my @expressions = (
'$.*' => [ map { ref $_ ? dclone $_ : $_ } values %data ],
'$.store.book[*].title' => [ map { $_->{title} } @{ $data{store}{book} } ],
);
do_test(@expressions);
};
subtest recursive => sub {
my @expressions = (
'$..nonexistent' => [],
'$..foo' => [qw/bar baz bak/],
'$..complex_array[?(@.weight > 10)].classification.quux' =>
[ map { $_->{classification}{quux} } grep { $_->{weight} > 10 } @{ $data{complex_array} } ],
'$..key2.subkey1' => ['2value1'],
'$..book[-1:]' => [ $data{store}{book}->[-1] ],
);
do_test(@expressions);
};
subtest 'slice and union' => sub {
my @expressions = (
'$.array[0,1]' => [ @{ $data{array} }[ ( 0, 1 ) ] ],
'$.array[1:3]' => [ @{ $data{array} }[ ( 1 .. 2 ) ] ],
'$.array[-1:]' => [ $data{array}->[-1] ],
'$.long_hash.key1[subkey1,subkey2]' => [ @{ $data{long_hash}{key1} }{qw/subkey1 subkey2/} ],
);
do_test(@expressions);
};
done_testing;
sub do_test {
my @expressions = @_;
while ( my $expression = shift @expressions ) {
my $expected = shift @expressions;
my @got;
lives_and {
@got = JSON::Path::Evaluator::evaluate_jsonpath( $json, $expression );
cmp_bag( \@got, $expected );
}
qq{"$expression" evaluated correctly};
}
}
sub sample_json {
my $data = <<END;
{
"simple" : "Simple",
"hash" : {
"key" : "value"
},
"long_hash" : {
"key1" : {
"subkey1" : "1value1",
"subkey2" : "1value2",
"subkey3" : {
"subsubkey1" : "1value11",
"subsubkey2" : "1value12"
}
},
"key2" : {
"subkey1" : "2value1",
"subkey2" : "2value2",
"subkey3" : {
"subsubkey1" : "2value11",
"subsubkey2" : "2value12"
}
}
},
"array" : [
"alpha",
"beta",
"gamma",
"delta",
"kappa"
],
"complex_array" : [
{
"quux" : 1,
"weight" : 20,
"classification" : {
"quux" : "omega",
"quuy" : "omicron"
},
"foo" : "bar",
"type" : {
"name" : "Alpha",
"code" : "CODE_ALPHA"
}
},
{
"quux" : 0,
"weight" : 10,
"classification" : {
"quux" : "lambda",
"quuy" : "nu"
},
"foo" : "baz",
"type" : {
"name" : "Beta",
"code" : "CODE_BETA"
}
},
{
"weight" : 30,
"classification" : {
"quux" : "eta",
"quuy" : "zeta"
},
"foo" : "bak",
"type" : {
"name" : "Gamma",
"code" : "CODE_GAMMA"
}
}
],
"multilevel_array" : [
[
[
"alpha",
"beta",
"gamma"
],
[
"delta",
"epsilon",
"zeta"
]
],
[
[
"eta",
"theta",
"iota"
],
[
"kappa",
"lambda",
"mu"
]
]
],
"subkey1" : "DO NOT WANT",
"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
}
]
}
}
END
return $data;
}