使用 JSON.pm 跟踪类型

keeping track of type with JSON.pm

假设我输入了以下 JSON 对象

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

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

我不想以字段名称为基础,因为我正在尝试编写一些通用的东西,并且字段名称可能会更改。

使用 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