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

This goes back to a previous post, which I've somewhat resolved myself, but still have one outstanding issue: I am looking to grab and store the value of each overall json line value first. Example: from the below code, I want to actually read and store in a variable through a while loop and store 1, 2, 3, etc.
{ "1": {"subject1": "value", "subject2": [{"subject3": "value", "subject +4": "value"}], "subject5": "value", "subject6": value, "subject7": "v +alue"}, "2": {"subject1": "value", "subject2": [{"subject3": "value", "subject +4": "value"}], "subject5": "value", "subject6": value, "subject7": "v +alue"}, "3": {"subject1": "value", "subject2": [{"subject3": "value", "subject +4": "value"}], "subject5": "value", "subject6": value, "subject7": "v +alue"} }
(etc...) I currently already can store subject1's value as well as the array of subject2 and grab its subject3 value.
my $jsonfeed = (above json format!) my $json = new JSON; my $data = $json->decode($jsonfeed); my $value = "$data->{1}->{subject1}"; foreach my $array(@{$data->{1}->{subject2}}){ my %hash = (); $hash{subject3} = $array->{subject3}; }
So this is all nice, but I need to store the first value of each {} sequence which is listed here as 1{}, 2{}, 3, etc as well in a variable, and then loop the whole thing in one giant while or foreach loop. I can't seem to grab every value, however, of $data->{$_}. Anyone have a good idea?

Replies are listed 'Best First'.
Re: JSON Structure Question
by stephen (Priest) on May 22, 2013 at 22:00 UTC

    If you want to get, say, the value of "subject1" of each sequence, the easiest way is with the values keyword, as in:

    my $data = $json->decode($jsonfeed); my @values = (); foreach my $value ( values %{ $data } ) { push(@values, $value->{'subject1'}); } print Dumper( \@values );

    Which returns

    $VAR1 = [ 'value', 'value', 'value' ];

    I'm not too clear on what values you're looking for, so I hope this helps.

    stephen

Re: JSON Structure Question
by roboticus (Chancellor) on May 23, 2013 at 13:10 UTC

    omegaweaponZ:

    Untested, but I'd try something like:

    for my $key (sort keys %$data) { # $key should be 1, 2, then 3 here... for my $subject (sort keys {$data->{$key}) { # $subject should be subject1, then subject 2 here if ($subject eq "subject1") { print "$data->{$key}{$subject}\n"; } elsif ($subject eq "subject2" { # subject2 has arrayref of one item, # an href, with two keys: print "$data->{$key}{$subject}[0]{subject3}\n"; print "$data->{$key}{$subject}[0]{subject4}\n"; } } }

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.

      This is the closest to what I'm looking for, as I can generate all the hashes, but I have yet to get each value. Just to clarify, I already can get every other value within the parenthesis of each json line, So everything within 1 {} I can get! The issue is I actually want to record and store the value of 1 itself, and 2, and 3, and so on, in one giant for loop that encompasses my ability to grab the values of each array within, so they are all assigned line by line
        Figured it out, hash was the way to approach this. But simplistically, all I needed to do was:
        my %hash = %{ $data }; while (my ($key, $value) = each %hash) { print "$key : $value \n";
        Instant first level report out
Re: JSON Structure Question
by hdb (Monsignor) on May 23, 2013 at 14:07 UTC

    The following code prints all the "leaves" of a complex data structure but you can add selection criteria operating on the keys as required.

    use strict; use warnings; use JSON; my %dispatch = ('' => sub { print "$_[0]\n"; }, 'HASH' => sub { for my $key (keys %{$_[0]}) { search_and_replace_in_hash( $_[0]->{$key} +); } }, 'ARRAY' => sub { search_and_replace_in_hash( $_ ) for @{$_[0]}; + }, 'default' => sub { my ( $element, $op ) = @_; print STDERR ref($element).": unknown type of +reference\n" }, ); sub search_and_replace_in_hash { &{ $dispatch{ ref($_[0]) } // $dispatch{'default'} }(@_); } my $data = <<EOD; { "1": {"subject1": "value", "subject2": [{"subject3": "value", "subject +4": "value"}], "subject5": "value", "subject6": "value", "subject7": +"value"}, "2": {"subject1": "value", "subject2": [{"subject3": "value", "subject +4": "value"}], "subject5": "value", "subject6": "value", "subject7": +"value"}, "3": {"subject1": "value", "subject2": [{"subject3": "value", "subject +4": "value"}], "subject5": "value", "subject6": "value", "subject7": +"value"} } EOD $data = JSON->new()->decode( $data ); search_and_replace_in_hash( $data );
      The closest way of explaining what I need is that I need to store not just what is in each hash key of 1{}. 2{}, but I physically need to store the top most level of each hash key. The json format cannot be modified in any way.

      I can use $data->{1}->{stuff} to get the value of stuff, and so on. So what am I missing to simply read through and loop line by line and get $data->{??????}. I would like to stick with the JSON package to learn the format structure better before exploring other packages.

Re: JSON Structure Question
by Anonymous Monk on May 23, 2013 at 02:25 UTC