Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSON formatting in Perl

Tags:

json

perl

I am trying to create a JSON object that lists maps associated to a particular user, but haven't ever worked with nested JSON objects. This is what I want:

{
   "success":"list of users maps",
   "maps":[
      {
         "id":"1",
         "name":"Home to LE",
         "date_created":"1366559121"
      },
      {
         "id":"2",
         "name":"Test 1",
         "date_created":"1366735066"
      }
   ]
}

with this perl code:

  my $maps = [];
  for (my $x = 0; $x < $sth->rows; $x++) {
    my ($id, $name, $date) = $sth->fetchrow_array();
    my $map = qq{{"id":"$id","name":"$name","date_created":"$date"}};
    push $maps, $map;
  }
  my $j = JSON::XS->new->utf8;
  my $output = $j->encode({
    "success"=>"list of users maps",
    "maps"=>$maps
  });

But the output I am getting is:

{
   "success":"list of users maps",
   "maps":[
      "{\"id\":\"1\",\"name\":\"Home to LE\",\"date_created\":\"1366559121\"}",
      "{\"id\":\"2\",\"name\":\"Test 1\",\"date_created\":\"1366735066\"}"
   ]
}

So when I process it in my Javascript, the data.maps[x].id is undefined. I am pretty sure that the JSON being output is incorrectly formatted.

Can anyone help me fix it?

like image 586
skeniver Avatar asked Apr 23 '13 17:04

skeniver


1 Answers

It's undefined because what you have at data.maps[x] is not an object, but a string. Since a string has no property called id, you're getting undefined. I'd probably do something like this (if I couldn't change the perl script):

var mapData = JSON.parse(data.maps[x]);
//do stuff with mapData.id

But the better thing to do, is to make sure that it doesn't encode it as a string, but as proper JSON.

This part in your perl script:

my $map = qq{{"id":"$id","name":"$name","date_created":"$date"}};

Is simply making a quoted string out of all that data. Instead, what you want is an actual perl hash that can be translated into a JSON map/associative-array. So try this:

my $map = {
    "id" => "$id",
    "name" => "$name",
    "date_created" => "$date"
};
push $maps, $map;

This way you actually have a perl hash (instead of just a string) that will get translated into proper JSON.

As an example, I wrote some test code:

use strict;
use JSON::XS;

my $maps = [];
push $maps, { id => 1, blah => 2 };
push $maps, { id => 3, blah => 2 };

my $j = JSON::XS->new->utf8->pretty(1);
my $output = $j->encode({
    success => "list of blah",
    maps => $maps
});

print $output;

When you run this, you get:

{
   "success" : "list of blah",
   "maps" : [
      {
         "blah" : 2,
         "id" : 1
      },
      {
         "blah" : 2,
         "id" : 3
      }
   ]
}
like image 138
Vivin Paliath Avatar answered Sep 22 '22 12:09

Vivin Paliath