Skip Menu |

This queue is for tickets about the JSON-PP CPAN distribution.

Report information
The Basics
Id: 111634
Status: open
Priority: 0/
Queue: JSON-PP

People
Owner: Nobody in particular
Requestors: SAFRONOV [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: (no value)
Fixed in: (no value)



Subject: JSON returns numbers as quoted strings based on variable's POK flag
Initially problem described here: http://www.perlmonks.org/?node_id=1062358 If the variable $x has been interpolated into a string (e.g. print "$x\n"), and thus acquires a POK flag indicating that the SV structure has a pointer to a string then JSON module returns it as e.g. '"0.99"', not as expected 0.99. the code in JSON module: sub value_to_json { my ($self, $value) = @_; return 'null' if(!defined $value); my $b_obj = B::svref_2object(\$value); # for round trip problem my $flags = $b_obj->FLAGS; return $value # as is if $flags & ( B::SVp_IOK | B::SVp_NOK ) and !( $flags & B::SVp_POK ); # SvTYPE is IV or NV?
On 2016-02-01 12:49:06, SAFRONOV wrote: Show quoted text
> Initially problem described here: > http://www.perlmonks.org/?node_id=1062358 > > If the variable $x has been interpolated into a string (e.g. print > "$x\n"), and thus acquires a POK flag indicating that the SV structure > has a pointer to a string then JSON module returns it as e.g. > '"0.99"', not as expected 0.99. > > the code in JSON module: > > sub value_to_json { > my ($self, $value) = @_; > > return 'null' if(!defined $value); > > my $b_obj = B::svref_2object(\$value); # for round trip problem > my $flags = $b_obj->FLAGS; > > return $value # as is > if $flags & ( B::SVp_IOK | B::SVp_NOK ) and !( $flags & B::SVp_POK ); > # SvTYPE is IV or NV?
It seems that print "$x\n" does not set POK starting with perl 5.20, so JSON.pm does what you want here: $ perl5.18.4 -MJSON -e '$x=1.1; print "$x\n"; warn encode_json [$x]' 1.1 ["1.1"] at -e line 1. $ perl5.20.0 -MJSON -e '$x=1.1; print "$x\n"; warn encode_json [$x]' 1.1 [1.1] at -e line 1. Also it seems that the alternative module JSON::Create does the right thing for older perls (checked only with 5.18.4): $ perl5.18.4 -MJSON::Create=create_json -e '$x=1.1; print "$x\n"; warn create_json [$x];' 1.1 [1.1] at -e line 1.
Show quoted text
> It seems that print "$x\n" does not set POK starting with perl 5.20, > so JSON.pm does what you want here: > > $ perl5.18.4 -MJSON -e '$x=1.1; print "$x\n"; warn encode_json [$x]' > 1.1 > ["1.1"] at -e line 1. > $ perl5.20.0 -MJSON -e '$x=1.1; print "$x\n"; warn encode_json [$x]' > 1.1 > [1.1] at -e line 1. > > Also it seems that the alternative module JSON::Create does the right > thing for older perls (checked only with 5.18.4): > > $ perl5.18.4 -MJSON::Create=create_json -e '$x=1.1; print "$x\n"; warn > create_json [$x];' > 1.1 > [1.1] at -e line 1.
Indeed p5.22 works as expected, no quotes. What if print() behavior would be changed eventually? Is OK to use POK flag? Isn't that a dirty hack? /v
Subject: [rt.cpan.org #111634]
Date: Tue, 24 May 2016 22:58:46 +0200
To: bug-JSON [...] rt.cpan.org
From: "Frédéric Buclin" <lpsolit [...] gmail.com>
This problem is not fixed in 5.20.1 if you write: perl -MJSON -wE '$x=30; print "$x\n"; warn encode_json [$x]' 30 ["30"] at -e line 1. Why is the behavior different with integers?
RT-Send-CC: lpsolit [...] gmail.com
On 2016-02-03 17:50:15, SREZIC wrote: Show quoted text
> On 2016-02-01 12:49:06, SAFRONOV wrote:
> > Initially problem described here: > > http://www.perlmonks.org/?node_id=1062358 > > > > If the variable $x has been interpolated into a string (e.g. print > > "$x\n"), and thus acquires a POK flag indicating that the SV > > structure > > has a pointer to a string then JSON module returns it as e.g. > > '"0.99"', not as expected 0.99. > > > > the code in JSON module: > > > > sub value_to_json { > > my ($self, $value) = @_; > > > > return 'null' if(!defined $value); > > > > my $b_obj = B::svref_2object(\$value); # for round trip problem > > my $flags = $b_obj->FLAGS; > > > > return $value # as is > > if $flags & ( B::SVp_IOK | B::SVp_NOK ) and !( $flags & B::SVp_POK ); > > # SvTYPE is IV or NV?
> > It seems that print "$x\n" does not set POK starting with perl 5.20, > so JSON.pm does what you want here: > > $ perl5.18.4 -MJSON -e '$x=1.1; print "$x\n"; warn encode_json [$x]' > 1.1 > ["1.1"] at -e line 1. > $ perl5.20.0 -MJSON -e '$x=1.1; print "$x\n"; warn encode_json [$x]' > 1.1 > [1.1] at -e line 1. > > Also it seems that the alternative module JSON::Create does the right > thing for older perls (checked only with 5.18.4): > > $ perl5.18.4 -MJSON::Create=create_json -e '$x=1.1; print "$x\n"; warn > create_json [$x];' > 1.1 > [1.1] at -e line 1.
And speaking of alternatives: it seems that Cpanel::JSON::XS behaves better than JSON::XS or JSON:PP. Here some systematic tests: Integer (IV): $ for i in $(ls /opt/perl-5.*/bin/perl | fgrep -v 5.21.); do echo -n "$i "; $i -MJSON::XS -wE 'my $x=30; my $y="$x"; print encode_json [$x],"\n"'; done /opt/perl-5.10.1/bin/perl ["30"] /opt/perl-5.16.3/bin/perl ["30"] /opt/perl-5.20.0/bin/perl ["30"] /opt/perl-5.20.3/bin/perl ["30"] /opt/perl-5.22.1/bin/perl ["30"] /opt/perl-5.22.2/bin/perl ["30"] /opt/perl-5.24.0/bin/perl ["30"] /opt/perl-5.25.1/bin/perl ["30"] $ for i in $(ls /opt/perl-5.*/bin/perl | fgrep -v 5.21.); do echo -n "$i "; $i -MCpanel::JSON::XS -wE 'my $x=30; my $y="$x"; print encode_json [$x],"\n"'; done /opt/perl-5.10.1/bin/perl [30] /opt/perl-5.16.3/bin/perl [30] /opt/perl-5.20.0/bin/perl [30] /opt/perl-5.20.3/bin/perl [30] /opt/perl-5.22.1/bin/perl [30] /opt/perl-5.22.2/bin/perl [30] /opt/perl-5.24.0/bin/perl [30] /opt/perl-5.25.1/bin/perl [30] Float (NV): $ for i in $(ls /opt/perl-5.*/bin/perl | fgrep -v 5.21.); do echo -n "$i "; $i -MJSON::XS -wE 'my $x=30.0; my $y="$x"; print encode_json [$x],"\n"'; done /opt/perl-5.10.1/bin/perl ["30"] /opt/perl-5.16.3/bin/perl ["30"] /opt/perl-5.20.0/bin/perl [30] /opt/perl-5.20.3/bin/perl [30] /opt/perl-5.22.1/bin/perl [30] /opt/perl-5.22.2/bin/perl [30] /opt/perl-5.24.0/bin/perl [30] /opt/perl-5.25.1/bin/perl [30] $ for i in $(ls /opt/perl-5.*/bin/perl | fgrep -v 5.21.); do echo -n "$i "; $i -MCpanel::JSON::XS -wE 'my $x=30.0; my $y="$x"; print encode_json [$x],"\n"'; done /opt/perl-5.10.1/bin/perl [30.0] /opt/perl-5.16.3/bin/perl [30.0] /opt/perl-5.20.0/bin/perl [30.0] /opt/perl-5.20.3/bin/perl [30.0] /opt/perl-5.22.1/bin/perl [30.0] /opt/perl-5.22.2/bin/perl [30.0] /opt/perl-5.24.0/bin/perl [30.0] /opt/perl-5.25.1/bin/perl [30.0] (JSON::XS and JSON::PP behave the same in these tests)