Vijay Boyapati
Vijay Boyapati

Reputation: 7708

Converting array of numbers to json in perl, getting array of strings

I'm trying to convert an array of numbers to json:


   $json = to_json("numbers_array" => \@numbers_array);
   print $json;

but the output I'm getting is:

  {"numbers_array" => ["1","2","3"] }

I'm building up the array by adding elements using push(). How do I convert to json and retain the numeric type, so that the output is:

  {"numbers_array" => [1,2,3]}

Thanks!

Upvotes: 4

Views: 1722

Answers (3)

Rubyd
Rubyd

Reputation: 11

In addition to earlier answers: it's not a question of the definition of your data but of usage.

From the JSON::XS pod:

JSON::XS will encode […] scalars that have last been used in a string context before encoding as JSON strings, and anything else as number value

Consider this piece of code:

use JSON::XS;
my $numbers = [123,124,125];
print "A number: $numbers->[1]\n";            #<- use 2nd entry in string context.
print JSON::XS->new->encode ($numbers)."\n";

It prints:

A number: 124
[123,"124",125]

Would you have expected that number 124 be encoded as string? Beware!

(I learned that the hard way chasing a heisenbug that only showed up when I had some debug logging active.)

Upvotes: 1

David W.
David W.

Reputation: 107060

Here's my program:

#! /usr/bin/env perl

use strict;
use warnings;
use feature qw(say);

use JSON;

my @array;
for my $number ( (1..5) ) {
    push @array, $number;
}
say to_json( {"number_array" => \@array} );

And here's my result:

{"number_array":[1,2,3,4,5]}

That's what you want. Right?

Let's change my push from push @array , $number; to push @array "$number"; where $number is in quotes as if it's a string:

#! /usr/bin/env perl

use strict;
use warnings;
use feature qw(say);

use JSON;

my @array;
for my $number ( (1..5) ) {
    push @array, "$number";
}
say to_json( {"number_array" => \@array} );

Now I get:

{"number_array":["1","2","3","4","5"]}

Somehow JSON was able to detect that these numbers were pushed in as strings. Let me loop again and add a zero to each element:

#! /usr/bin/env perl

use strict;
use warnings;
use feature qw(say);

use JSON;

my @array;
for my $number ( (1..5) ) {
    push @array, "$number";
}

@array  = map { $_ += 0 } @array; #Add a 0 to each element

say to_json( {"number_array" => \@array} );

Back to:

{"number_array":[1,2,3,4,5]}

Looks like you have to add a zero to each element of your array to convert the string back to a numeric value.

Upvotes: 0

hmatt1
hmatt1

Reputation: 5149

From the JSON documentation:


You can force the type to be a number by numifying it:

   my $x = "3"; # some variable containing a string
   $x += 0;     # numify it, ensuring it will be dumped as a number
   $x *= 1;     # same thing, the choice is yours.

I would try something like this:

    $json = to_json({numbers_array => [map { $_ + 0 } @numbers_array]});
    print $json;

Upvotes: 7

Related Questions