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

I want to check whether a JSONPath in a corresponding file exists, independent of the type of value associated with it (i.e., a scalar, array, object). The following code is near to what I am l looking for.

I test whether the path's value is defined, which works fine except for the case that the value associated with the path is "null": The path obviously exists, but the program indicates that it is not existant:

#!/usr/bin/perl use JSON::Path; $json = q({ "key": "value", "object": { "elem1": "value1", "elem2": "v +alue2" }, "array": [ 0, 1], "not_defined": null }); $json_path[0] = JSON::Path->new( "\$.key" ); $json_path[1] = JSON::Path->new( "\$.object" ); $json_path[2] = JSON::Path->new( "\$.non_exist" ); $json_path[3] = JSON::Path->new( "\$.array" ); $json_path[4] = JSON::Path->new( "\$.not_defined" ); for ( $i=0; $i<=$#json_path; $i++) { print "Path $json_path[$i] "; if ( defined $json_path[$i]->values( $json ) ) { print( "exists\n" ) ; } else { print( "does not exist\n" ) } }

The output is:

Path $.key exists Path $.object exists Path $.non_exist does not exist Path $.array exists Path $.not_defined does not exist

How can I do this properly?

Replies are listed 'Best First'.
Re: How to properly check a JSONPath for existance?
by kroach (Pilgrim) on Apr 02, 2018 at 16:24 UTC

    The documentation says the values() method returns the number of matches but it doesn't seem to be the case since in your example it returns undef for both a non-existent element and a null one. Since you check for defined(), they both return false.

    What you can do is call values() in list context and check for the number of matches. The non-existent entry should have none and null should have a single undef entry.

    my @values = $json_path[$i]->values($json); if (@values > 0) { print("exists\n"); } else { print("does not exist\n") }

      Works! Thanks a lot!

Re: How to properly check a JSONPath for existance?
by Your Mother (Archbishop) on Apr 03, 2018 at 04:04 UTC

    kroach gave the right answer but since it's Perl, partly :P, and since I'd never heard of JSON::Path before this, I want to show the way I would have approached it before learning there was a more native tool (from our own tobyink); with Data::Diver (update to correct oversight: from our own tye) and JSON.

    use strictures; use JSON; use Data::Diver "Dive"; my $json = <<''; { "key" : "value" ,"object" : { "elem1": "value1", "elem2": "value2" } ,"array" : [ 0, 1 ] ,"not_defined" : null } my $data = decode_json $json; for my $key (qw/ key object non_exist array not_defined /) { my @exists = Dive( $data, $key ); printf "%20s -> %s\n", $key, @exists ? "yeppers" : "nopers"; } __END__ key -> yeppers object -> yeppers non_exist -> nopers array -> yeppers not_defined -> yeppers