perl
use strict;
use warnings;
use JSON::PP;
use FindBin;
use lib "$FindBin::Bin/../lib";
use JQ::Lite;
my $query = shift or die "Usage: $0 '.query'\n";
my $json_text = do { local $/; <STDIN> };
m
y $jq = JQ::Lite->new;
my @results = $jq->run_query($json_text, $query);
my $pp = JSON::PP->new->utf8->canonical->pretty;
for my $r (@results) {
if (!defined $r) {
print "null\n";
}
:More;
use JQ::Lite;
my $json = <<'JSON';
[
{"name": "Alice", "age": 30},
{"name": "Bob", "age": 25}
]
JSON
my $jq = JQ::Lite->new;
my @results = $jq->run_query($json, '.[] | {"name": .name}'
],
'object constructor builds hashes with selected fields',
);
@results = $jq->run_query($json, '.[] | {name: .nickname}');
is_deeply(
\@results,
[
{ name => undef },
ng values are represented as null entries in constructed objects',
);
@results = $jq->run_query($json, '.[] | {}');
is_deeply(
\@results,
[ {}, {} ],
'empty object constructors yield emp
Q::Lite;
my $json = q({
"nums": [1, 9, 3, 2],
"words": ["apple", "pear", "banana"],
"mixed": ["10", "2", "30"]
});
my $jq = JQ::Lite->new;
my @desc_nums = $jq->run_query($json, '.nums | sor
t_desc');
my @desc_words = $jq->run_query($json, '.words | sort_desc');
my @desc_mixed = $jq->run_query($json, '.mixed | sort_desc');
is_deeply($desc_nums[0], [9, 3, 2, 1], 'numeric sort descendin
ew;
my $json = <<'JSON';
{
"users": [
{ "name": "Alice", "age": 30 },
{ "name": "Bob", "age": 22 },
{ "name": "Carol", "age": 19 }
]
}
JSON
my @res1 = $jq->run_query($json, '.users
| count');
is_deeply(\@res1, [3], 'count users');
my @res2 = $jq->run_query($json, '.users[] | select(.age > 25) | count');
is_deeply(\@res2, [1], 'count users over 25');
done_testing;
$json = <<'JSON';
{
"items": [
"text",
42,
true,
null,
{"note": "object"},
[1, 2, 3]
],
"flag": false
}
JSON
my $jq = JQ::Lite->new;
my @results = $jq->run_query($json,
;
isa_ok($results[2], 'JSON::PP::Boolean', 'scalars preserves boolean objects');
ok(!defined $results[3], 'scalars keeps null values as undef');
@results = $jq->run_query($json, '.items | scalars');
alars yields no output for array containers');
@results = $jq->run_query($json, '.flag | scalars');
isa_ok($results[0], 'JSON::PP::Boolean', 'scalars passes through scalar booleans');
ok(!$results[0]
rnings;
use Test::More tests => 4;
use JSON::PP;
use JQ::Lite;
my $jq = JQ::Lite->new;
# --- 1. Empty array
my $json1 = '[]';
my @result1 = $jq->run_query($json1, 'is_empty');
ok($result1[0], 'is_em
n-empty array
my $json2 = '[1,2,3]';
my @result2 = $jq->run_query($json2, 'is_empty');
ok(!$result2[0], 'is_empty() returns false for non-empty array');
# --- 3. Empty hash
my $json3 = '{}';
my @resu
$jq->run_query($json3, 'is_empty');
ok($result3[0], 'is_empty() returns true for empty hash');
# --- 4. Non-empty hash
my $json4 = '{"key":"value"}';
my @result4 = $jq->run_query($json4, 'is_empty');
More;
use JQ::Lite;
my $json = q({
"nums": [5, 3, 5, 1, 3],
"words": ["banana", "apple", "banana", "pear"]
});
my $jq = JQ::Lite->new;
my @sorted = $jq->run_query($json, '.nums | sort');
my @un
te;
my $json = q({
"score": "42",
"raw": "n/a",
"flag": true,
"nested": [["10", "oops"], [false, "0"]],
"maybe": null
});
my $jq = JQ::Lite->new;
my @scalar = $jq->run_query($json, '.scor
my @boolean = $jq->run_query($json, '.flag | to_number');
is($boolean[0], 1, 'to_number converts JSON booleans to numeric values');
my @string = $jq->run_query($json, '.raw | to_number');
is($strin
ery($json, '.nested | to_number');
is_deeply(
$array[0],
[[10, 'oops'], [0, 0]],
'to_number recurses through arrays preserving non-numeric entries'
);
my @maybe = $jq->run_query($json, '.
ngs;
use Test::More;
use JQ::Lite;
my $json = <<'JSON';
{
"users": ["Alice", "Bob", "Carol"]
}
JSON
my $jq = JQ::Lite->new;
is_deeply([$jq->run_query($json, '.users | nth(0)')], ['Alice'], 'nth(0
jq->run_query($json, '.users | nth(1)')], ['Bob'], 'nth(1) is Bob');
is_deeply([$jq->run_query($json, '.users | nth(2)')], ['Carol'], 'nth(2) is Carol');
is_deeply([$jq->run_query($json, '.users | nth
use Encode qw(decode);
use JQ::Lite;
my $json = decode('UTF-8', '"こんにちは!"');
my $jq = JQ::Lite->new;
my @results = eval { $jq->run_query($json, '@uri') };
my $error = $@;
is($error,
gs;
use Test::More;
use JQ::Lite;
my $json = <<'JSON';
{
"items": [[1, 2], [3], [], [4, 5]]
}
JSON
my $jq = JQ::Lite->new;
my @results = $jq->run_query($json, '.items | flatten');
is_deeply(\@res
use Test::More;
use JQ::Lite;
my $json = q([
{ "value": 10 },
{ "value": 30 },
{ "value": 20 }
]);
my $jq = JQ::Lite->new;
my ($add) = $jq->run_query($json, 'map(.value) | add');
is($add, 60
jq->run_query($json, 'map(.value) | sum');
is($sum, 60, 'sum = 60');
my ($min) = $jq->run_query($json, 'map(.value) | min');
is($min, 10, 'min = 10');
my ($max) = $jq->run_query($json, 'map(.value)
s($max, 30, 'max = 30');
my ($avg) = $jq->run_query($json, 'map(.value) | avg');
is($avg, 20, 'avg = 20');
my ($variance) = $jq->run_query($json, 'map(.value) | variance');
ok(abs($variance - 66.666
use strict;
use warnings;
use Test::More;
use JSON::PP;
use JQ::Lite;
my $json = <<'JSON';
{
"items": [
{ "name": "Widget", "value": 1 },
{ "value": 2, "active": true },
{ "nested": { "
],
"single": { "foo": "bar" },
"no_hashes": ["alpha", "beta"]
}
JSON
my $jq = JQ::Lite->new;
my @merged = $jq->run_query($json, '.items | merge_objects');
is_deeply(
\@merged,
[
e => JSON::PP::true,
nested => { id => 42 },
}
],
'merge_objects folds arrays of objects into one hash with later values winning',
);
my @single = $jq->run_query($json, '.
my $json = q({
"numbers": [1, 2, 3, 4],
"user": { "name": "Alice" }
});
my $jq = JQ::Lite->new;
my @drop_0 = $jq->run_query($json, '.numbers | drop(0)');
my @drop_2 = $jq->run_query($json, '.n
umbers | drop(2)');
my @drop_5 = $jq->run_query($json, '.numbers | drop(5)');
my @non_array = $jq->run_query($json, '.user | drop(1)');
is_deeply($drop_0[0], [1, 2, 3, 4], 'drop(0) keeps all elements
;
use JQ::Lite;
use JSON::PP qw(encode_json decode_json);
my $jq = JQ::Lite->new;
my $json = encode_json({ matrix => [ [1, 2, 3], [4, 5, 6] ] });
my @result = $jq->run_query($json, '.matrix | transp
sult[0], $expected, 'transpose pivots arrays of arrays');
$json = encode_json({ jagged => [ [1, 2], [3] ] });
@result = $jq->run_query($json, '.jagged | transpose');
$expected = [ [1, 3] ];
is_deeply
transpose truncates to the shortest row');
$json = encode_json({ numbers => [1, 2, 3] });
my $decoded = decode_json($json);
@result = $jq->run_query($json, '.numbers | transpose');
is_deeply($result[
package JQ::Lite::Util;
use strict;
use warnings;
use JSON::PP ();
use List::Util qw(sum min max);
use Scalar::Util qw(looks_like_number);
use MIME::Base64 qw(encode_base64 decode_base64);
use Encod
;
my $JSON_DECODER = JSON::PP->new->utf8->allow_nonref;
my $FROMJSON_DECODER = JSON::PP->new->utf8->allow_nonref;
my $TOJSON_ENCODER = JSON::PP->new->utf8->allow_nonref;
sub _encode_json {
eturn $TOJSON_ENCODER->encode($value);
}
sub _decode_json {
my ($text) = @_;
if (defined $text && is_utf8($text, 1)) {
$text = encode('UTF-8', $text);
}
return $JSON_DECODER
@next_results = ();
for my $item (@results) {
my $json = JQ::Lite::Util::_encode_json($item);
for my $segment (@sequence_parts) {
}
}
my @outputs = $self->run_query($json, $filter);
push @next_results, @outputs;
}
}
t;
}
my $json = JQ::Lite::Util::_encode_json($item);
my @outputs = $self->run_query($json, $element);
if (@outputs) {
my $json_ordered = q([1, 2, 3, 4, 5]);
my ($p0) = $jq->run_query($json_ordered, 'percentile(0)');
my ($p25) = $jq->run_query($json_ordered, 'percentile(25)');
my ($p50) = $jq->run_query($json_order
ed, 'percentile');
my ($p100) = $jq->run_query($json_ordered, 'percentile(100)');
is($p0, 1, 'percentile(0) returns the minimum value');
is($p25, 2, 'percentile(25) returns the first quartile');
is($
) returns the maximum value');
my $json_interp = q([10, 20, 30, 40]);
my ($p90) = $jq->run_query($json_interp, 'percentile(0.90)');
my ($p75) = $jq->run_query($json_interp, 'percentile(75)');
is($p9
package JQ::Lite::Expression;
use strict;
use warnings;
use JSON::PP (); # lightweight decoder for string literals
use Scalar::Util qw(looks_like_number);
# Internal constant used to signal that
next;
}
if ($char eq '"') {
my ($consumed, $value) = _consume_json_string($expr, $i);
return unless defined $consumed;
$i += $consumed;
ar;
$i++;
}
$path =~ s/\s+$//;
return ($i - $start, $path);
}
sub _consume_json_string {
my ($expr, $start) = @_;
my $i = $start;
my $len = length $expr;
my $
use strict;
use warnings;
use Test::More;
use JQ::Lite;
my $json = q({
"users": [
{
"name": "Alice",
"friends": [ { "name": "Charlie" }, { "name": "Dave" } ]
},
{
"nam
iends": [ { "name": "Eve" } ]
}
]
});
my $jq = JQ::Lite->new;
my @result = $jq->run_query($json, ".users[].friends[].name");
is_deeply(\@result, ['Charlie', 'Dave', 'Eve'], 'Multi-level array