ingydotnet / yaml-libyaml-pm

Perl Binding to libyaml
http://search.cpan.org/dist/YAML-LibYAML/
33 stars 37 forks source link

Load(): Numbers should be numbers only #68

Open perlpunk opened 6 years ago

perlpunk commented 6 years ago

Numbers loaded from YAML have a PV additionally to IV / NV. Modules like JSON::PP/XS don't recognize them as a number and put quotes around them:

use YAML::XS qw/ Load /;
use JSON::PP qw/ encode_json /;
use Devel::Peek qw/ Dump /;
my $yaml = "foo: 23";
my $data = Load $yaml;
my $json = encode_json($data);
say $json;
Dump $data->{foo};
__DATA__
{"foo":"23"}
SV = PVIV(0x56152ab23bb0) at 0x56152ab1e7b8
  REFCNT = 1
  FLAGS = (IOK,POK,pIOK,pPOK)
  IV = 23
  PV = 0x56152abfb680 "23"\0
  CUR = 2
  LEN = 10
karenetheridge commented 4 years ago

I just ran into this issue. Is the fix straightforward?

perlpunk commented 4 years ago

I'm not sure. I guess it should be easy. Currently this code is used:

scalar = newSVpvn(string, length);
SvIV_please(scalar);

https://github.com/ingydotnet/yaml-libyaml-pm/blob/master/LibYAML/perl_libyaml.c#L467 https://github.com/ingydotnet/yaml-libyaml-pm/blob/master/LibYAML/perl_libyaml.c#L563

Not sure which would be the correct function.

perlpunk commented 4 years ago

The good news is that the newest JSON::PP and Cpanel::JSON::XS default to number when both flags are set. But this should still be fixed here.

Leont commented 1 year ago

I'm not sure. I guess it should be easy. Currently this code is used:

scalar = newSVpvn(string, length);
SvIV_please(scalar);

https://github.com/ingydotnet/yaml-libyaml-pm/blob/master/LibYAML/perl_libyaml.c#L467 https://github.com/ingydotnet/yaml-libyaml-pm/blob/master/LibYAML/perl_libyaml.c#L563

Not sure which would be the correct function.

I guess you need something along the lines of

if (looks_like_number(scalar)) {
    if (SvNV(scalar) == SvIV(scalar))
        SvIV_only(scalar);
    else
        SvNV_only(scalar);
}