编码json,没有数值引用

时间:2014-07-17 20:50:00

标签: json perl

我有一个perl代码段

use JSON::XS;
$a = {"john" => "123", "mary" => "456"};
print encode_json($a),"\n";

输出

{"john":"123","mary":"456"}

不知道是否有一个选项可以使encode_json函数(来自JSON :: XS模块)对其进行编码,以使值(123,456)不被双引号包围。即,像

{"john":123,"mary":456}

不幸的是我无法更改$ a中的哈希,因为它是从另一个函数传递给我的。想知道在encode_json()上是否有任何技巧。

谢谢!

2 个答案:

答案 0 :(得分:4)

在JSON序列化之前,您可能需要自己预处理数据。

此解决方案使用Data::Leaf::Walker遍历任意结构,将字符串转换为数字。

use JSON;
use Data::Leaf::Walker;
use Scalar::Util qw();

my $a = {"john" => "123",
         "mary" => ["456","aa"],
         "fred" => "bb",
         "nested" => {"Q" => undef, "A" => 42},
         };

my $walker = Data::Leaf::Walker->new( $a );

while (my ( $key_path, $value ) = $walker->each ) {
    $walker->store($key_path, $value + 0)
        if Scalar::Util::looks_like_number $value;
};

print  to_json($a);

输出:{"john":123,"nested":{"A":42,"Q":null},"mary":[456,"aa"],"fred":"bb"}

答案 1 :(得分:2)

您不应直接使用JSON::XS,只有JSON已加载JSON::XS(如果有)。

Perl中的标量被标记为是字符串还是数字,在这里您提供字符串。从您的数字中删除引号,它们应显示为不引用,因为JSON已经自动执行此操作。

如果您正在阅读字符串(例如数据库),那么您可以将字符串强制转换为这样的数字:

{ john => 0+$john, mary => 0+$mary }


更新,这是一个递归替换:

#!/usr/bin/env perl
use JSON;
use Modern::Perl;
use Scalar::Util qw( looks_like_number );

my $structure = {
    john => "123",
    mary => 456,
    deeper => {
        lucy => "35zz",
        names => [
            "john",
            "123",
            456,
        ],
    },
};

sub make_numbers_recursively {
    my ( $data ) = shift;

    if ( ref $data eq 'HASH' ) {

        # Replace hash values with recurisvely updated values
        map { $data->{ $_ } = make_numbers_recursively( $data->{ $_ } ) } keys %$data;

    } elsif ( ref $data eq 'ARRAY' ) {

        # Replace each array value with recursively processed result
        map { $_ = make_numbers_recursively( $_ ) } @$data;

    } else {

        $data += 0 if looks_like_number( $data );

    }

    return $data;
}

my $json = JSON->new->pretty;
say $json->encode( $structure );
make_numbers_recursively( $structure );
say $json->encode( $structure );

输出:

{
   "mary" : 456,
   "deeper" : {
      "names" : [
         "john",
         "123",
         456
      ],
      "lucy" : "35zz"
   },
   "john" : "123"
}

{
   "mary" : 456,
   "deeper" : {
      "names" : [
         "john",
         123,
         456
      ],
      "lucy" : "35zz"
   },
   "john" : 123
}

请注意,它会就地修改结构,因此如果您需要原始数据,您可能需要首先CloneData::Clone