【问题标题】:keeping track of type with JSON.pm使用 JSON.pm 跟踪类型
【发布时间】:2015-01-16 00:59:03
【问题描述】:

假设我有以下输入的 JSON 对象

{
   "field1": 21,
   "field2": "21",
   "field3": "hello"
}

decode_json 或 from_json 有什么方法可以知道值的原始类型是什么(数字与字符串)?我知道 Perl 通常不关心类型,但我需要知道原始类型是什么。我也知道 perl 在创建 JSON 对象时确实会跟踪类型(因此在创建 JSON 对象时它确实区分“21”和 21,所以我希望有一种方法可以在解码/“来自”时保留该信息记住它。

我不想将它基于字段名称,因为我试图编写一些通用的东西,并且字段名称可能会改变。

【问题讨论】:

  • 那不是 JSON。 jsonlint.com
  • 只是出于病态的好奇心...为什么需要区别对待 21"21"
  • 我下线了一段时间.. 与 mongo 和 mongoose 有关。在发送之前将 perl 对象转换为正确的 mongo 字段。

标签: json perl


【解决方案1】:

使用 JSON::XS 时,标量中值的类型与文档中值的类型相匹配。

$ perl -e'
   use strict;
   use warnings;

   use B        qw( svref_2object SVf_IOK SVf_NOK SVf_POK );
   use JSON::XS qw( decode_json );

   my $data = decode_json(q{[ "4", 4, 4.0, 20000000000000000000 ]});

   for my $i (0..$#$data) {
      my $sv = svref_2object(\( $data->[$i] ));
      my $flags = $sv->FLAGS;
      printf("Scalar %s has %s\n",
         $i,
         join(",",
            $flags & SVf_POK ? "PV" : (),
            $flags & SVf_IOK ? "IV" : (),
            $flags & SVf_NOK ? "NV" : (),
         ),
      );
   }
'
Scalar 0 has PV
Scalar 1 has IV
Scalar 2 has NV
Scalar 3 has PV

如您所见,第四个标量在使用 JSON::XS 时是一个例外。 JSON::XS 将非常大的数字存储为字符串以避免丢失精度。

使用 JSON::PP: 可以获得类似的结果:

Scalar 0 has PV
Scalar 1 has IV
Scalar 2 has NV
Scalar 3 has NV

【讨论】:

  • 这显然是一种极端情况,但是 JSON 数字仅由数字组成并且不能在 Perl 中表示为数字而不损失精度,则表示为字符串。
  • @ThisSuitIsBlackNot,我将您的评论纳入我的回答中。请注意,JSON::PP 将大数字存储为 NV。
  • 有趣,我没想到要使用JSON::PP 进行测试。看起来documentation 需要更新,因为没有提到那个特别的区别。
  • @ThisSuitIsBlackNot,实际上,20000000000000000000 可以无损地存储在 NV 中。但是 JSON::PP 也将 20000000000000000001 存储为 NV。
  • 我们结束了做一些不同的事情,但我接受了你的回答。抱歉耽搁了这么久,再也没有回答这个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-09
  • 2020-05-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多