Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer

No such pseudo-hash field

by nleach (Novice)
on Mar 28, 2011 at 11:00 UTC ( #895884=perlquestion: print w/replies, xml ) Need Help??

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

Hi, Still fumbling around trying to retrieve values from, for me, complicated data structures

This is what Dumper shows (I’ve both trimmed and anonymoused the data, but hopefully have not screwed the structure)

bless( { 'allowedHostnames' => [ 'node1', 'node2' ], 'customerName' => 'GarbageA', 'expirationDate' => '2021-08-15T22:59:59.000Z', 'errorMessage' => undef, 'properties' => [ bless( { 'value' => '42000', 'name' => 'maxEngines' }, 'Property' ), bless( { 'value' => '', 'name' => 'brokerLeases' }, 'Property' ), bless( { 'value' => '', 'name' => 'amazonDevPay' }, 'Property' ), bless( { 'value' => GarbageD', 'name' => 'customer_ID' }, 'Property' ), bless( { 'value' => ' GarbageE', 'name' => 'LicenseID' }, 'Property' ) ] }, 'LicenseInfo' )

I can successfully get “GarbageA” for customerName, but cannot get 42000 for maxEngines – the error returned is “No such pseudo-hash field maxEngines"

This is the code I am using

my $soap2 = SOAP::Lite->uri( $_[1] )->proxy( $_[2] )->getLicenseInfo() +; my @licenseInfos = $soap2->result ; for ( my $i = 0 ; $i < @licenseInfos ; $i++ ) { my $license = $licenseInfos[$i]; print Dumper($license); my $licensedCustomer = $license->{'customerName'}; print "$licensedCustomer\n"; my $maxEngine = $license->{'properties'}->{'maxEngines'}; print "$maxEngine\n"; }
Any help much appreciated. Regards, Nigel

Replies are listed 'Best First'.
Re: No such pseudo-hash field
by Eliya (Vicar) on Mar 28, 2011 at 11:10 UTC
    No such pseudo-hash field

    This is the error you typically get when you incorrectly access an array as a hash, and have an old Perl that still does support pseudo hashes (such as 5.8.x).

    In your specific case, your $license->{'properties'} is an arrayref, but you treat it as a hashref.

    Something like this should work better

    my $maxEngine; my $props = $license->{'properties'}; for my $p (@$props) { if ($p->{name} eq "maxEngines") { $maxEngine = $p->{value}; last; } }

    Or, if you know for sure that "maxEngines" always is the first array field, you can say

    my $maxEngine = $license->{properties}[0]{value};

    to retrieve the 42000.

Re: No such pseudo-hash field
by ELISHEVA (Prior) on Mar 28, 2011 at 11:40 UTC

    When you are trying to figure out how to access a part of a complex data structure, it is important to pay attention to each level of curly brace { and square bracket [. If you look carefully you should see a square brace next to {properties}. That means that hash member is storing an array reference. Within the array are a series of {...}. Each of those are array elements. Since the array element with the property name 'maxEngines' is in the first array element, you would access its associated value like this:

Re: No such pseudo-hash field
by moritz (Cardinal) on Mar 28, 2011 at 12:49 UTC
Re: No such pseudo-hash field
by nleach (Novice) on Mar 28, 2011 at 11:54 UTC

    Many thanks for both quick answers. Eliya’s first suggestion worked great.

    Theleftsock, I can see where your coming from, but that syntax did not work, it returned “Bad index while coercing array into hash

Re: No such pseudo-hash field
by theleftsock (Beadle) on Mar 28, 2011 at 11:22 UTC
    because the keys are actually 'name' and 'value'. the values are '42000' and 'maxengines'. you need more like this to get those values back. I did not load your data and test it. Hope that helps.
    my $maxEngine_name = $license->{'properties'}->{'name'}; my $maxEngine_value = $license->{'properties'}->{'value'};
    Have a nice day.

      This would still produce "No such pseudo-hash field" "Pseudo-hashes are deprecated" / "Argument "maxEngines" isn't numeric in hash element" / "Bad index while coercing array into hash" (with warnings on), because $license->{'properties'} is an arrayref (1).

      Rather, it should be

      my $maxEngine_name = $license->{'properties'}->[0]->{'name'}; my $maxEngine_value = $license->{'properties'}->[0]->{'value'};

      (presuming "maxEngines" corresponds to the first entry in the array)


      (1) the values which are being looked up internally via the "index hash" (first array elem) - i.e. "maxEngines" and "42000" here - are not useful as indices for the array/pseudo hash.

Re: No such pseudo-hash field
by Anonymous Monk on Mar 29, 2011 at 14:39 UTC

    In the unlikely event that no useful accessors are defined in the LicenseInfo package, then you could directly access the properties like so by mapping the array into a hash or a hashref (chosen in this case to match the style of the licenseinfo)

    foreach my $license (@licenseInfos) { my $licenseProperties = {map {$_->{name} => $_->{value}} @{$licens +e->{properties}}}; print $license->{customerName}, "\n"; print $licenseProperties->{maxEngines}, "\n"; }

Log In?

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

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (3)
As of 2021-10-28 19:48 GMT
Find Nodes?
    Voting Booth?
    My first memorable Perl project was:

    Results (96 votes). Check out past polls.