如何避免使用Perl JSON模块在数字周围加引号?

Ale*_*ber 2 perl json google-visualization

有没有办法让encode_json方法不在数字上加引号?

例如,我在CentOS 6.3上使用perl 5.10(在Win 7上也使用ActiveState perl 5.16),它将引号放在不应该的位置:

# perl -MJSON -e 'print encode_json({a => [split(",", "1.2,30")]});'
{"a":["1.2","30"]}
Run Code Online (Sandbox Code Playgroud)

也就是说,好的是,它在上面的代码中看到"1.2"和"30"作为字符串,但我的问题是:

我的perl脚本解析的CSV文件,并生成HTML的文件,使用谷歌图表,而后者是通过具有围绕数字值引号(eventhough我告诉他们,列的类型是"数字")混淆.

作为一种变通方法我通过数据迭代意象结构和更换每一个数字sprintf "%f", $val,但是这会导致过多的空值的每个数字,这使得图表无误后所显示的,但难看:

# perl -e 'printf "%f", "30"'
30.000000
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

更新:

是的,添加零或乘以1 似乎在第一眼就能起作用:

# perl -MJSON -e 'print encode_json({a => [map {1 * $_} split(",", "1.2,30")]});'
{"a":[1.2,30]}
Run Code Online (Sandbox Code Playgroud)

但在我的真实脚本中,它仍然不适用于浮动数字.

您也可以在使用Dumper模块时看到CLI中仍然存在的问题:

# perl -MData::Dumper -e 'print Dumper({a => [map {1.0 * $_} split(",", "1.2,30")]});'
$VAR1 = {
          'a' => [
                   '1.2', # <= THIS IS MY PROBLEM AND CONFUSES GOOGLE CHARTS
                   30
                 ]
        };
Run Code Online (Sandbox Code Playgroud)

sim*_*onp 11

您的问题是,虽然您正确地将其转换为数字,但在调用encode_json之前,它会被转换回字符串.这是因为您在调试语句中调用Data :: Dumper.如果你注释掉你对Data :: Dumper的调用,你会发现encode_json输出正确的东西.

例如,此示例显示在对象上调用Dumper之前和之后的JSON对象:

$ perl -MData::Dumper -MJSON -e '
my $obj = {a => [map { $_ - 0 } split(",", "1.2,30")]};
print "JSON before: ",encode_json($obj),"\n";
print "Dumper: ",Dumper($obj);
print "JSON after: ",encode_json($obj),"\n";
'
JSON before: {"a":[1.2,30]}
Dumper: $VAR1 = {
          'a' => [
                   '1.2',
                   30
                 ]
        };
JSON after: {"a":["1.2",30]}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,Dumper实际上会修改您正在转储的对象,从而影响您后续的encode_json调用.

  • 谢谢.翻车机也是我的问题.我从未怀疑一个据称只读的动作正在修改它的输入. (2认同)
  • 我有完全相同的问题...我也震惊Data :: Dumper正在修改它的参数! (2认同)

gpo*_*ojd 9

你已经有了这个答案,但我想指出在Perl中这样做的惯用方法.从现代Perl的第10章:

要确保Perl将值视为数字,请添加零:

my $numeric_value = 0 + $value;
Run Code Online (Sandbox Code Playgroud)

为了确保Perl将值视为boolean,double否定它:

my $boolean_value = !! $value;
Run Code Online (Sandbox Code Playgroud)

要确保Perl将值视为字符串,请将其与空字符串连接:

my $string_value = '' . $value;
Run Code Online (Sandbox Code Playgroud)


Que*_*tin 6

它们作为字符串出现,因为你得到了字符串split.

可能有更好的方法,但将它们乘以1似乎有效:

perl -MJSON -e 'print encode_json({a => [map { $_ * 1  } split(",", "1.2,30")]});'
Run Code Online (Sandbox Code Playgroud)