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

Hi monks

I want to POST a data structure (array of hashes) from a Perl script to a cgi on a server. I am doing something wrong with references and dereferencing, I guess.

My Perl script

#!/usr/bin/perl use strict; use LWP; use HTTP::Request::Common; my @AoH = ( { husband => "barney", wife => "betty", son => "bamm bamm", }, { husband => "george", wife => "jane", son => "elroy", }, { husband => "homer", wife => "marge", son => "bart", }, ); my $url = 'http://myurl.com/cgi-bin/memo.pl'; my $ua = LWP::UserAgent->new; my $request = POST($url, Content => [data=>[@AoH]]); my $response = $ua->request($request); print $response->content, "\n";

And to get the data on the server:

#!/usr/bin/perl -Tw use strict; use CGI qw(:standard); use CGI::Carp qw(fatalsToBrowser); use Data::Dumper qw(Dumper); print header; my $q = CGI->new(); my @data = $q->param('data'); if (param('data')) { print "you sent ", param('data'); } else { print "error"; ; } foreach my $href (@data) { foreach my $key (keys(%$href)) { print "key: $key, value: $href->{$key}\n"; } }

I get an error message "Can't use string ("ARRAY(0x818064)") as a HASH ref" and if I print Dumper @data I can not - no matter what I try - dereference the hashes in the array. What am I doing wrong?

Replies are listed 'Best First'.
Re: POST array of hashes CGI
by LanX (Saint) on Nov 26, 2018 at 15:44 UTC
    Post can only handle strings, and the array_ref is stringified to "ARRAY(0x818064)".

    you need to serialize/deserialize the data, either with Data::Dumper or JSON.

    I'd rather prefer JSON, because deserializing with eval is risky.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery FootballPerl is like chess, only without the dice

    PS: And as a next step don't try to handle an array_ref as a hash_ref.

Re: POST array of hashes CGI
by 1nickt (Canon) on Nov 26, 2018 at 15:41 UTC

    Hi, you sent the memory address of the AOH as the value of the data param! You need to serialize your data into a string of some kind first, see e.g. JSON.

    Hope this helps!


    The way forward always starts with a minimal test.
Re: POST array of hashes CGI
by IB2017 (Pilgrim) on Nov 26, 2018 at 16:54 UTC

    Thank you for your knowledge. However, if I serialize the data structure (in this case with JSON):

    my $json = to_json( { myData => \@AoH } ); my $url = 'http://myweb.com/cgi-bin/memo.pl'; my $ua = LWP::UserAgent->new; my $request = POST($url, Content => [data=>[$json]]); $request->header( 'Content-Type' => 'application/json' ); my $response = $ua->request($request); print $response->content, "\n";

    And change my cgi accordingly:

    print header; my $q = CGI->new(); my $json = $q->param('data'); my $decoded_json = decode_json( $json );; print Dumper $decoded_json;

    I get the following error: ">malformed JSON string, neither tag, array, object, number, string or atom, at character offset 0 (before "(end of string)")"

    So there is still something I am missing in POST, any idea? Possible that I can not pass JSON data with "param"?

      Hi, it's most common nowadays to pass JSON around in requests and responses as the entire body (see, e.g., almost any API you use). Try this:

      #use HTTP::Request::Common; use HTTP::Request; my $request = HTTP::Request->new(POST => $url); $request->header( 'Content-Type' => 'application/json' ); $request->content( $json ); ...
      ... and ...
      my $json = $query->param('POSTDATA'); my $data = decode_json( $json ); ...
      (see https://metacpan.org/pod/release/LDS/CGI.pm-3.43/CGI.pm#HANDLING_NON-URLENCODED_ARGUMENTS)

      Hope this helps!


      The way forward always starts with a minimal test.

      In your client script the value for the data param is a listref but in your server script you treat it as a scalar. You need to be consistent, ie. use a scalar for both.

        Mmmm, but if I just make my server script as simple as:

        my $q = CGI->new(); my $json = $q->param('data'); print Dumper $json;

        I get as result $VAR1 = undef; which sounds strange to me. Am I missing something?