Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

How to access an array in a JSON file which is the root element (using JSON::Path)

by Bloehdian (Beadle)
on Apr 01, 2018 at 21:55 UTC ( [id://1212113]=perlquestion: print w/replies, xml ) Need Help??

Bloehdian has asked for the wisdom of the Perl Monks concerning the following question:

I intend to print the elements of an array stored in a JSON file using JSON::Path with the following Perl one-liner:

perl -e 'use JSON::Path; $json = "[ \"string1\", \"string2\" ]"; $json_path = JSON::Path->new( "\$" ); foreach $elem ( @{$json_path->values( $json )} ) { print "##$elem##" . "\n" }'

But instead of the strings contained in the array surrounded by two pairs of hashes I just get the warning:

Use of uninitialized value in string eq at /usr/local/share/perl/5.20.2/JSON/Path/Evaluator.pm line 108.

I would expect that the JSONPath "$" would address the root element in the JSON file (which is an array) and, hence, $json_path->values( $json ) would point to a list/ an array with the elements being the strings "string1" and "string2". Dereferencing $json_path->values( $json ) would deliver the array whose elements could be printed out then.

But obviously I am wrong.

How can I properly address an array in a JSON file which is the root element?

Replies are listed 'Best First'.
Re: How to access an array in a JSON file which is the root element (using JSON::Path)
by davido (Cardinal) on Apr 01, 2018 at 22:13 UTC

    If you want the entire content of the array you would probably use this path:

    $.[0:]

    values() will not return an array reference, in that case, but rather a list of the array's contents. So your foreach loop would look like this:

    foreach $elem ($json_path->values($json)) { ... }

    In other words, no need to dereference to get a list. You're getting a list in the first place.

    Also, instead of all those backslash escapes, consider using q{['string1', 'string2']}. This is much easier to read than "[\"string1\", \"string2\"]".

    Update: So, the entire one-liner would probably be better written like this:

    perl -MJSON::Path -Mstrict -wE 'my $json = q{["string1","string2"]}; m +y $json_path = JSON::Path->new(q{$.[0:]}); foreach my $elem ($json_pa +th->values($json)) {say "##$elem$$"}'

    Here we're using the -M command line switch to 'use' the JSON::Path module. We can use that switch as many times as we need, so we could also have said, "-Mwarnings". I also used the -E switch, which loads more modern Perl features. In this case I used it to gain a say keyword to use in place of print. Doing so allowed me to not have to append a newline. A small but convenient savings in one-liners. And I used the -w switch to enable warnings (I could have achieved a similar effect by using -Mwarnings. Finally, despite this being a throwaway one-liner, I used lexical variables, mostly out of habit, but also partially because it's a good way to catch typos in variable names, which can be a factor even in short one-liners.

    We're not doing this to count keystrokes, but it's worth pointing out that adding strictures, warnings, say, lexical my variables, and a thicker quoting construct (q{...} vs "...") improved the quality of the one-liner and at the same time didn't increase its size. We used fewer keystrokes while cutting down on the difficult portions like escaping quote characters, as well as the tedious parts like appending newlines.


    Dave

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1212113]
Approved by kcott
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (9)
As of 2024-04-19 13:18 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found