0

It seems that printing a hash value to a file may change something internally.

The following code snippet will print (notice there is double quote around 1.6):

{"john":4,"mary":"1.6"}

Code snippet:

use JSON::XS;

$a = {};
$a->{john} += "4"; 
$a->{mary} += "1.6";
open ($fd, ">tmp.txt") || die "Failed to open file to write $!\n";
print $fd "$a->{mary}";
close $fd;
$b = encode_json($a);
print "$b\n";

If I comment out the 3 lines on writing to a file in the above:

open ($fd, ">tmp.txt") || die "Failed to open file to write $!\n";
print $fd "$a->{mary}";
close $fd;

it will print without double-quote around 1.6.

{"john":4,"mary":1.6}

My perl is 5.14.2 running on Ubuntu 12.04 64bit, the JSON::XS module has version 3.01.

Wonder if what is causing this. Thanks.

packetie
  • 4,839
  • 8
  • 37
  • 72
  • `+` is only defined on numbers. When you use `+=` above it implicit converts the arguments to numbers. Try using `.=` – Hunter McMillen Aug 06 '14 at 15:16
  • There's more discussion of this issue here: [Peculiar incident: printing a variable changes its type](http://www.perlmonks.org/?node_id=1062356) – Paul Roub Aug 06 '14 at 15:17
  • Thanks guys, the links help. Wish there is a way to instruct perl intepreter to keep it as numbers, since I would like the encoded json string not have double quote around numbers. – packetie Aug 06 '14 at 15:31

2 Answers2

2

It seems that printing a hash value to a file may change something internally.

No, but passing a string to the addition operator does.

$ perl -MDevel::Peek -e'$x="1.2"; Dump($x); 0+$x; Dump($x);' 2>&1 | grep FLAGS
  FLAGS = (POK,pPOK)
  FLAGS = (NOK,POK,pIOK,pNOK,pPOK)
  • POK = Contains a string.
  • NOK = Contains a floating point number.

Passing a copy of the string will avoid this.

$ perl -MDevel::Peek -e'$x="1.2"; Dump($x); 0+"$x"; Dump($x);' 2>&1 | grep FLAGS
  FLAGS = (POK,pPOK)
  FLAGS = (POK,pPOK)
ikegami
  • 367,544
  • 15
  • 269
  • 518
  • thanks for pointing it out and the code snippets. Found out that the operation "$a->{mary}\n" changed the internal type of $a->{mary}. – packetie Aug 06 '14 at 16:17
  • @codingFun, Not if it has the value you say it has. But if `$a->{mary}` wasn't a string, then yes, concatenation could add a string to the scalar. A string treated as a number can add one or more numerical representations to the scalar. A number treated as a string can add a string representation to the scalar. – ikegami Aug 06 '14 at 16:49
  • $a->{mary} has a numerical value to begin with. I would like it to remain numerical when it goes into encode_json so that the numbers don't have an extra double quote. String concatenation like $tmp = "$a->{mary}\n"; obvious changed it which beats my purpose. Sorry for the confusion and thanks for the discussion! – packetie Aug 06 '14 at 17:20
0

Thanks to the links by @ThisSuitIsBlackNot and @Paul Roub, I made a slight change so that the encoded json string doesn't have the double quote around numbers:

open ($fd, ">tmp.txt") || die "Failed to open file to write $!\n";
$x = $a->{mary};
print $fd $x;
close $fd;

Basically I just assigned a hash value to an intermediate variable and print the intermediate variable.

packetie
  • 4,839
  • 8
  • 37
  • 72