in reply to POST array of hashes CGI

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"?

Replies are listed 'Best First'.
Re^2: POST array of hashes CGI
by 1nickt (Canon) on Nov 26, 2018 at 17:36 UTC

    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.
Re^2: POST array of hashes CGI
by hippo (Archbishop) on Nov 26, 2018 at 17:02 UTC

    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?

        You need to set a Content-Type header, and use the special CGI.pm parameter name POSTDATA to access the body of the POST request. This works for me:

        Server:

        #!/usr/bin/perl -T use warnings; use strict; use CGI; use CGI::Carp qw(fatalsToBrowser); use Data::Dumper qw(Dumper); use JSON::MaybeXS qw/decode_json/; my $q = CGI->new(); print $q->header; my $data = $q->param('POSTDATA'); $data = decode_json($data) if $data; print Dumper($data);

        Client:

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

        Output on client:

        $VAR1 = { 'data' => [ { 'son' => 'bamm bamm', 'husband' => 'barney', 'wife' => 'betty' }, { 'son' => 'elroy', 'wife' => 'jane', 'husband' => 'george' }, { 'husband' => 'homer', 'wife' => 'marge', 'son' => 'bart' } ] };