meltdown90
meltdown90

Reputation: 261

Perl Dancer - JSON serializer and JSON arrays

I have a problem working with the built in Perl Dancer serializer for JSON and JSON arrays.

I activated the serializer in the app.pl file:

#!/usr/bin/env perl
use Dancer;
use main;

set serializer => 'JSON';

dance;

In the module itself I tested the JSON parsing like this:

post '/test/' => sub {
    my $params = request->params;

    debug('Test: ', $params);
};

Now I wanted to make sure the JSON gets parsed as expected, so I tried using cURL to understand the way the serializer works:

curl -H "Content-Type: application/json" -X POST http://localhost:3000/test/ -d '{ "Name" : "foo", "email" : "bar" }'

The result was as expected:

Test: {'Name' => 'foo','email' => 'bar'}

But trying to send an array:

curl -H "Content-Type: application/json" -X POST http://localhost:3000/test/ -d '[{ "Name" : "foo", "email" : "bar" }]'

Resulted in:

Test: {}

I expected the serializer to return an array reference, but it seems like it returns an empty hash. I tried using the serializer the other way around, but encoding JSONs seems to work as expected. What have I done wrong?

Upvotes: 5

Views: 2369

Answers (2)

jr.
jr.

Reputation: 4675

I have come across this same problem. The Dancer serializer framework cannot de-serialize anything other than HASH data types. I suspect this is because internally in Dancer you can do things such as params->{'foo'} to get elements. This code in Dancer::Serializer (~line 110) is the reason for this.

if (!ref $new_params or ref $new_params ne 'HASH') {
    return $request;
}

For me, there are some methods where I need to pass in an array to the request. This was causing me not to be able to use the standard serializer framework, but I wanted to keep the same options in my config.yml.

Here is my solution:

  my $json_object = from_json(request->body, config->{'engines'}->{'JSON'});

This will return a JSON object (Array or HashRef) using the configuration option you have specified in your config.yml for the JSON engine. You may or may not want to wrap this in an eval.

Upvotes: 1

user3183018
user3183018

Reputation: 364

Thought I had code that did this but, was mistaken.

I couldn't get params to parse anything with any depth. Maybe that's by design but, not really clear to me from the documentation.

Using the from_json function directly you can parse request->body which contains the POST'd JSON string:

Note: I use'd Data::Dumper to print variable contents to try to make it a little clearer.

post '/test/' => sub {
 #my @params =   params  ;
 #my @params =   request->body;
 my $body = request->body;

 my $j_O = from_json( $body );

 #deubg( 'Test1: ' . Dumper( request->body ) );
 #debug( 'Test2: ' . Dumper( request->params ) );
 #debug( 'Test3: ' . Dumper( { params }  ) );
 debug( 'Test4: ' . Dumper( $body ) );
 debug( 'Test5: ' . Dumper( $j_O ) );


};

OUTPUT:

[27993] debug @0.001528> [hit #2]Test4: $VAR1 = '[ { "Name" : "foo", "email" : "bar" }, { "Name" : "bar"} ]'; in /media/truecrypt1/Projects/Perl5+/Dancer/Test/lib/Test.pm l. 23
[27993] debug @0.001772> [hit #2]Test5: $VAR1 = [
          {
            'email' => 'bar',
            'Name' => 'foo'
          },
          {
            'Name' => 'bar'
          }
        ];

Upvotes: 4

Related Questions