Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Convert string to hash

by gabrielsousa (Sexton)
on Mar 27, 2017 at 17:18 UTC ( [id://1186098]=perlquestion: print w/replies, xml ) Need Help??

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

i have this code
foreach my $value (values $jsonhash{results} ) { print Dumper $value; }
the output
$VAR1 = { 'subnet_id' => undef, 'sp_name' => undef, 'image_name' => undef, 'ptable_name' => undef, 'global_status_label' => 'OK', 'uuid' => undef, 'model_name' => 'VMware Virtual Platform', 'provision_method' => 'build', 'configuration_status' => 0, 'operatingsystem_id' => 12, 'capabilities' => [ 'build' ], 'id' => 265, 'mac' => '00:50:56:91:c2:c1', 'enabled' => bless( do{\(my $o = 1)}, 'JSON::backportPP::Boo +lean' ), 'image_file' => '', 'environment_name' => 'production', 'use_image' => undef, 'name' => 'adm003.siege.red', 'sp_mac' => undef, 'architecture_id' => 1, 'operatingsystem_name' => 'RedHat 7.2', 'medium_name' => undef, 'configuration_status_label' => 'No changes', 'updated_at' => '2017-03-27 17:14:42 UTC', 'compute_resource_id' => undef, 'installed_at' => undef, 'puppet_ca_proxy_id' => 1, 'realm_id' => undef, 'disk' => undef, 'ip' => '192.168.133.37', 'model_id' => 1, 'owner_type' => 'User', 'subnet_name' => undef, 'certname' => 'adm003.siege.red', 'hostgroup_id' => 45, 'created_at' => '2016-11-21 15:54:36 UTC', 'compute_profile_id' => undef, 'compute_resource_name' => undef, 'environment_id' => 1, 'global_status' => 0, 'image_id' => undef, 'domain_id' => 1, 'ptable_id' => undef, 'last_report' => '2017-03-27 17:14:29 UTC', 'sp_ip' => undef, 'architecture_name' => 'x86_64', 'sp_subnet_id' => undef, 'puppet_status' => 0, 'build' => bless( do{\(my $o = 0)}, 'JSON::backportPP::Boole +an' ), 'managed' => $VAR1->{'build'}, 'domain_name' => 'siege.red', 'medium_id' => undef, 'comment' => '', 'last_compile' => '2017-03-27 17:14:36 UTC', 'hostgroup_name' => 'base/barman', 'compute_profile_name' => undef, 'owner_id' => 8, 'puppet_proxy_id' => 1, 'realm_name' => undef };
how i convert the $value to an hash ?

Replies are listed 'Best First'.
Re: Convert string to hash
by AppleFritter (Vicar) on Mar 27, 2017 at 17:21 UTC
    Since the value returned appears to be a hash reference, %$value should be enough. That said depending on what you want to do you may not even need to do this, since you can indirectly access the hash's elements using e.g. $value->{'certname'} etc.
      worked
      %temp = %$value;
      how can i make this work (dont work)
      $certname = $value->{'certname'}; $temp{$certname} = %$value;
      i lose the %$value

        how can i make this work (dont work)

        Individual hash (and array) elements must be scalars. In order to store a more complex data structure, you have to store a reference — which is what $value already is. So assuming that this is what you want to do, and assuming %temp was previously declared as a hash,

        $certname = $value->{'certname'}; $temp{$certname} = $value;

        should do the trick.

        Building on AppleFritter's answers:

        You can combine the loop through your results with the hash-building using map, which transforms one list into another, while performing some action on each element. In this case the action would be to add the appropriate key and value to your hash. (And we can transform the first list into a hash because a hash is a list of pairs ...)

        my %json_hash = however_you_got_it(); my %new_hash = map { $_->{'certname'} => $_ } values %{ $json_hash{'r +esults'} };
        Here map takes each element of the list returned by values(), which is a hashref, extracts the value of its key 'certname', uses that as the key in the new hash, and uses the entire hashref as the value.

        Also note that I dereferenced the hashref $json_hash{'results'} before using it, because it's not "stable" Perl code to call values() (or keys()) on a hashref. I imagine you got a warning like "values on reference is experimental at ...", no?

        Hope this helps!


        The way forward always starts with a minimal test.
      just added the'\' and worked :)
      foreach my $value (values $jsonhash{results} ) { $temp{$value->{'certname'}} = \%$value; }

        That works, but it is unnecessary, since \ and % are complements, in a sense, and cancel each other out: % dereferences a hash reference ($value), i.e. gives you the hash it references; \ then gives you a reference to this hash again.

        There's nothing wrong with doing it this way, but I encourage you to get a good grip on references (hash or not). You'll often encounter them in Perl, and nested data structures don't work without them at all.

        It's cheaper to throw away a % than to add a \ ...

        Your solution is silly. Read perlreftut to find out why ... worth your time!


        The way forward always starts with a minimal test.
Re: Convert string to hash
by kcott (Archbishop) on Mar 28, 2017 at 08:33 UTC

    G'day gabrielsousa,

    After looking at your OP, and subsequent discussions in various parts of this thread, I think your issues probably revolve around one or more of the following.

    • Not having a complete understanding of what the original data structure looks like.
    • Using a highly experimental feature (possibly in error).
    • Gaps in your knowledge of Perl's data structures and references.

    Given the output you show, $jsonhash{results} is a hashref with a single key. The complete hash looks something like this:

    %jsonhash = ( results => { single_key => { subnet_id => undef, ..., certname => 'adm003.siege.red', ..., realm_name => undef } }, ... );

    Here's how you might investigate that structure. For illustrative purposes, and brevity (to show examples as one-liners), I'm using this highly simplified version of your structure:

    %h = (r => { x => { a => 1, b => 2 }})

    and I've set up this alias:

    $ alias perld='perl -Mstrict -Mwarnings -MData::Dump -E'

    Here's a representation of %jsonhash:

    $ perld 'my %h = (r => { x => { a => 1, b => 2 }}); dd \%h' { r => { x => { a => 1, b => 2 } } }

    Here's a representation of $jsonhash{results}:

    $ perld 'my %h = (r => { x => { a => 1, b => 2 }}); dd $h{r}' { x => { a => 1, b => 2 } }

    Here's a representation of the single key in $jsonhash{results}:

    $ perld 'my %h = (r => { x => { a => 1, b => 2 }}); dd $h{r}{x}' { a => 1, b => 2 }

    As there's only one key, there's no need for a loop; however, here it is using non-experimental code:

    $ perld 'my %h = (r => { x => { a => 1, b => 2 }}); dd $_ for values % +{$h{r}}' { a => 1, b => 2 }

    As you can see, the result is the same as that without the loop. Switching to an old version of Perl (v5.14.0), that implements the experimental feature, you can see there's no change in the output:

    $ perlbrew switch perl-5.14.0t $ perld 'my %h = (r => { x => { a => 1, b => 2 }}); dd $_ for values $ +h{r}' { a => 1, b => 2 }

    And, just for completeness, here it is again, using a more recent Perl (v5.24.0) and postfix dereference:

    $ perlbrew switch perl-5.24.0t $ perld 'my %h = (r => { x => { a => 1, b => 2 }}); dd $_ for values $ +h{r}->%*' { a => 1, b => 2 }
    "how i convert the $value to an hash ?"

    Firstly, consider whether you really want, or indeed need, to do this. If you do, two options should now be obvious:

    %{ $jsonhash{results}{single_key} } $jsonhash{results}{single_key}->%*

    Elsewhere, you were trying to get the value of 'certname'. You don't need any convoluted referencing, dereferencing or temporary hashes; it's immediately available as:

    $jsonhash{results}{single_key}{certname}

    See also: "perlintro: Perl variable types" (although this is an introductory text, it has a lot of links to further information about complex data structures and references which I recommend); keys, values (recent - without experimental feature), http://perldoc.perl.org/5.22.0//functions/values.html (older values doco with experimental feature); Data::Dump.

    — Ken

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (3)
As of 2024-04-24 17:24 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found