http://qs1969.pair.com?node_id=11137217

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

Hi there Monks

I have to extract some values from a JSON data. I have a sample here where I cant get to one of the values in one of the blocks. I would like to have this as a result:

Yes: Mary Lou - 11111 | 1 Yes: Mary Lou - 22222 | 2 Yes: John De - 33333 | 1 Yes: Smith Doe - 4444 | 1 No sec value, just the name: Joseph D.

But I can not get to the value:
Yes: Mary Lou - 11111 | 1

Instead, I am getting just this:
Yes: Mary Lou - 22222 | 2 Yes: John De - 33333 | 1 Yes: Smith Doe - 4444 | 1 No sec value, just the name: Joseph D.

Any help on that?
#!/usr/bin/perl use strict; use warnings; use JSON::XS; use JSON qw( ); use Data::Dumper; my $json = '{ "required": [ { "docs": [ { "sec": "11111", "number": "1" } ], "docs": [ { "sec": "22222", "number": "2" } ], "name": "Mary Lou" }, { "docs": [ { "sec": "33333", "number": "1" } ], "name": "John De" }, { "docs": [ { "sec": "4444", "number": "1" } ], "name": "Smith Doe" }, { "name": "Joseph D." } ] }'; my $json_data = JSON->new; my $data = $json_data->decode($json); for my $dta ( @{ $data->{ required } || [] } ){ if( scalar @{ $dta->{ docs } || [] } ){ for my $doc_data ( @{ $dta->{ docs } || [] } ){ if( $doc_data->{'sec'} ) { print "\n Yes: $dta->{'name'} - $doc_data->{'sec'} | $doc_da +ta->{'number'} \n"; } } }else { warn "\n No sec value, just the name: $dta->{'name'} \n\n"; } }

Thanks for looking!

Replies are listed 'Best First'.
Re: Parsing nested JSON
by hippo (Bishop) on Oct 04, 2021 at 21:26 UTC

    The first hash in your array has duplicate keys. That's why you can't get to the value of the first key - it has already been overwritten. Dump the structure to see this.


    🦛

Re: Parsing nested JSON
by AnomalousMonk (Archbishop) on Oct 05, 2021 at 00:28 UTC
    my $json = '{ "required": [ { "docs": [ { "sec": "11111", "number": "1" } ], "docs": [ { "sec": "22222", "number": "2" } ], "name": "Mary Lou" }, ... }';

    It seems strange that the value of "docs" in the quoted code should be an array with a single hash element. Was the original intention to make this an array of hashes? The posted code for printing the decoded JSON suggests this. Making this change to the JSON string produces the desired output with the posted code:

    Win8 Strawberry 5.8.9.5 (32) Mon 10/04/2021 20:14:50 C:\@Work\Perl\monks >perl use strict; use warnings; use JSON; use Data::Dumper; my $json = '{ "required": [ { "docs": [ { "sec": "11111", "number": "1" }, { "sec": "22222", "number": "2" } ], "name": "Mary Lou" }, { "docs": [ { "sec": "33333", "number": "1" } ], "name": "John De" }, { "docs": [ { "sec": "4444", "number": "1" } ], "name": "Smith Doe" }, { "name": "Joseph D." } ] }'; my $json_data = JSON->new; my $data = $json_data->decode($json); for my $dta ( @{ $data->{ required } || [] }) { if (scalar @{ $dta->{ docs } || [] } ) { for my $doc_data (@{ $dta->{ docs } || [] }) { if ($doc_data->{'sec'}) { print "\n Yes: $dta->{'name'} - $doc_data->{'sec'} ", "| $doc_data->{'number'} \n"; } } } else { warn "\n No sec value, just the name: $dta->{'name'} \n\n"; } } ^Z Yes: Mary Lou - 11111 | 1 Yes: Mary Lou - 22222 | 2 Yes: John De - 33333 | 1 Yes: Smith Doe - 4444 | 1 No sec value, just the name: Joseph D.


    Give a man a fish:  <%-{-{-{-<

      I suspect that AnomalousMonk has given the correct answer to your previous post (Looping through an array) as well. Because there was nothing obviously wrong with that data (except for the translation from JSON to perl) , we assumed that your problem was with the code.
      Bill
Re: Parsing nested JSON (duplicate keys)
by LanX (Saint) on Oct 04, 2021 at 21:56 UTC
    Hippo already told you that the problem are duplicate keys in your JSON, but ... the answer is unfortunately more complex.

    Please see

    So your options are:

    • If you are the author of that JSON structure, please correct it.
    • Otherwise it's pretty unclear how the result after conversion should look like, since Perl definitely doesn't allow (well overwrites) duplicated keys.
    • If you are stuck with that format you can try to fiddle a solution with another module like JSON::Parse (see "SEE ALSO"), good luck!

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery