http://qs321.pair.com?node_id=651548


in reply to JSON and Perl Objects - How to access data?

The structure is a hashref that contains a single member with key "items" which consists of an arrayref that contains two hashrefs. So you have to dereference the arrayref to get its members something like this:
for my $item( @{$inventors_object->{items}} ){ print $item->{name} . "\n"; };
To change the data:
$inventors_object->{items}->[0}->{name} = 'new name';
To turn it back into a JSON string:
my $new_json = objToJson( $inventors_object );
update here is your mistake:
@inventors_array = $inventors_obj->{"items"};
You are trying to turn an arrayref into an array without dereferencing it. Instead you want:
@inventors_array = @{ $inventors_obj->{"items"} };

Replies are listed 'Best First'.
Re^2: JSON and Perl Objects - How to access data?
by Anonymous Monk on Jun 02, 2010 at 18:52 UTC
    Man... thanks a lot.. i am trying to find useful info abt JSON and perl and this is pretty much the only one with some practical information. I still have not understood it completely but my sincere thanks. can u explain it to me wat exactly happens when u convert from json to perl obj. im lost in all the hashref and arrayref you are talking abt. Is it the object's structure that you are talking abt? if you could enumerate i would be grateful. thanks
Re^2: JSON and Perl Objects - How to access data?
by Anonymous Monk on Sep 05, 2015 at 15:57 UTC
    So how would you take the next step and represent this data in perl. For instance, if at the end of all this I want @name to hold 'Theodor Nelson','Morton Heilig' ,and @id to hold '_333301','_13204' how would I do that? I tried my @names = @{ $inventors_array[1]->{"name"}    }; but that gives me
    Can't use string ("Morton Heilig") as an ARRAY ref while "strict refs" + in use
    I'm not trying to define $names[Morton Heilig] = something, I'm trying to define $names[1]=Morton Heiling, or alternatively $names{_13204} = 'Morton Heilig'

      Good job searching to find this old thread! Your question is not related to JSON, but rather to perl data structures. See perlref.

      You should get in the habit of using Data::Dumper to examine your complex data structures. In this case, you still were unclear on how to access the nested data, but examining the structure is always the first step.

      (Note that jsonToObject in the OP is deprecated.)

      Here's an example that shows how to get your arrays. It's commented so you can see what's going on, and it deliberately uses more steps than optimal to be clear (if you really wanted to build separate arrays, you should probably use map).

      #!/usr/bin/perl use strict; use warnings; use feature qw/ say /; use Data::Dumper; use JSON; my $data = qq# { "items" : [ { "name" : "Theodor Nelson", "id": "_333301" }, { "name": "Morton Heilig", "id": "_13204" } ] } #; my $obj = from_json( $data ); my @names; my @ids; say Dumper $obj; # $obj is an anonymous hash with one key, 'items' my @items = @{ $obj->{'items'} }; # The value of the key 'items' is an anonymous array. # Here for simplicity we copy it into a new array. # We access it by deferencing it using @{ } foreach my $item ( @items ) { # Each element of the anonymous array is a hashref. # So $item is a hashref, not a scalar my $name = $item->{'name'}; my $id = $item->{'name'}; push @names, $name; push @ids, $id; } say 'Names: ' . join ', ', @names; say 'IDs: ' . join ', ', @ids; __END__
      A more idiomatic way to put the data into a hash keyed by ID as you suggested above:
      #!/usr/bin/perl use strict; use warnings; use feature qw/ say /; use Data::Dumper; use JSON; my $data = qq# { "items" : [ { "name" : "Theodor Nelson", "id": "_333301" }, { "name": "Morton Heilig", "id": "_13204" } ] } #; my $obj = from_json( $data ); my %names; $names{ $_->{'id'} } = $_->{'name'} for @{ $obj->{'items'} }; while ( my( $id, $name ) = each %names ) { say "$id: $name"; } __END__
      Output:
      $ perl 651544-2.pl _13204: Morton Heilig _333301: Theodor Nelson $
      And finally, how to access the names directly in the object:
      #!/usr/bin/perl use strict; use warnings; use feature qw/ say /; use Data::Dumper; use JSON; my $data = qq# { "items" : [ { "name" : "Theodor Nelson", "id": "_333301" }, { "name": "Morton Heilig", "id": "_13204" } ] } #; my $obj = from_json( $data ); say ${ $obj->{'items'}->[1] }{'name'}; # ^ ^ ^ ^ ^ ^ # | | | | | | # | is an arrayref | ----------- # | | | # | first element of which is a hash | # | | # the variable is value of the 'name' key __END__
      Hope this helps!

      The way forward always starts with a minimal test.

        Wow- that is awesome. Thank you for the well commented answer. I really appreciate it.

        I'm going to have to wrap my head around

        say ${ $obj->{'items'}->[1] }{'name'};

        but other than that I'm there. Thanks again!

        Really good ! small typo error... my $id = $item->{'id'}; # in line 37 instead of name, it should be id
      Use map
      my @names = map { $_->{name} } @inventors_array ; my @id = map { $_->{id} } @inventors_array ; my %names = map { $_->{id}, $_->{name} } @inventors_array;
      poj