4

We recently switched to the new JSON2 perl module. I thought all and everything gets returned quoted now. But i encountered some cases in which a number (250) got returned as unquoted number in the json string created by perl.

Out of curiosity: Does anyone know why such cases exist and how the json module decides if to quote a value?

hobbs
  • 223,387
  • 19
  • 210
  • 288
Thariama
  • 50,002
  • 13
  • 138
  • 166
  • 1
    Was the number unquoted in your source data structure? And btw, what "new JSON2 module"? – TLP Jun 12 '13 at 15:03
  • the number was unquoted in the source data structure. well, JSON2 is new to us - because of the work we had to put into a json module update we waited till now – Thariama Jun 12 '13 at 15:06
  • There is no module in CPAN named "JSON2". There are at least two modules with "JSON2" in their names. And there's a module "JSON", whose current version is 2.59. What exactly do you mean by "JSON2"? If you mean version 2 of "JSON", please update your question to say so. – Keith Thompson Jun 12 '13 at 15:45
  • @Keith: i am talking about the JSON module - the number just specifies its version – Thariama Jun 13 '13 at 07:57

2 Answers2

8

It will be unquoted if it's a number. Without getting too deeply into Perl internals, something is a number if it's a literal number or the result of an arithmetic operation, and it hasn't been stringified since its numeric value was produced.

use JSON::XS;
my $json = JSON::XS->new->allow_nonref;

say $json->encode(42);   # 42
say $json->encode("42"); # "42"

my $x = 4;
say $json->encode($x); # 4
my $y = "There are $x lights!";
say $json->encode($x); # "4"
$x++; # modifies the numeric value of $x
say $json->encode($x); # 5

Note that printing a number isn't "stringifying it" even though it produces a string representation of the number to output; print $x doesn't cause a number to be a string, but print "$x" does.

Anyway, all of this is a bit weird, but if you want a value to be reliably unquoted in JSON then put 0 + $value into your structure immediately before encoding it, and if you want it to be reliably quoted then use "" . $value or "$value".

hobbs
  • 223,387
  • 19
  • 210
  • 288
  • +1 i made a test and found out that JSON1 unqotes '12345', even though it has been a String before parsing. question: why does json1 create {"bar":"123","foo":"123"} here? – Thariama Jun 12 '13 at 15:18
1

You can force it into a string by doing something like this:

$number_str = '' . $number;

For example:

perl -MJSON -le 'print encode_json({foo=>123, bar=>"".123})'
{"bar":"123","foo":123}

It looks like older versions of JSON has autoconvert functionality that can be set. Did you not have $JSON::AUTOCONVERT set to a true value?

gpojd
  • 22,558
  • 8
  • 42
  • 71
  • You're quoting the wrong bit of the documentation; that's for JSON decoding, not encoding. – hobbs Jun 12 '13 at 15:13
  • Nice catch. I removed that part of my answer. – gpojd Jun 12 '13 at 15:13
  • +1 that is exactly the test i made. question: why does json1 create {"bar":"123","foo":"123"} here? – Thariama Jun 12 '13 at 15:19
  • @Thariama, because the value for foo is a number, it does not quote it. The value for bar is cast into a string, so it is quoted. Is it possible that you have the autoconvert flag set? See my updated answer. – gpojd Jun 12 '13 at 15:32
  • yes it is on, i checked my perl example program. the json1 documentation claimes that "By default, $JSON::AUTOCONVERT is true." – Thariama Jun 13 '13 at 07:56