6

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?

1 Answer 1

11

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
      }
   ]
}
Sign up to request clarification or add additional context in comments.

3 Comments

I should have realised the string issue myself! Thanks, I've changed the perl script and it works beautifully now!
Note that prior to Perl 5.14 push $maps, ... would have to be written as push @$maps, ....
And, starting in Perl v5.24, the "auto deref" in push $maps was removed. I've fixed that I the answer. effectiveperlprogramming.com/2016/04/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.