json - 为什么JSON编码需要引用Perl版本字符串?

标签 json perl oop

对于一些 Perl 诊断测试,我使用 JSON::MaybeXS 记录各种格式化为 JSON 的信息。

当我想记录当前的 Perl 版本时出现错误,这是我从特殊变量 $^V 获得的。

如最小演示脚本所示,除非我将 $^V 引用为“$^V”,否则会发生错误。

json_perl_version_test.pl

#!/usr/bin/env perl

use strict;
use warnings;
use v5.18;

use JSON::MaybeXS;

say "Running Perl version $^V";

my $item    = 'Wut?';

my %hash1   = (
    something   => $item,
    v_unquoted => $^V
);
eval { say say 'Hash1: ', encode_json \%hash1 };
say "Oops - JSON encode error: $@" if $@;

my %hash2   = (
    something   => $item,
    v_quoted => "$^V"
);
say 'Hash2: ', encode_json \%hash2;

# Running Perl version v5.34.0
# Oops - JSON encode error: encountered object 'v5.34.0', 
# but neither allow_blessed, convert_blessed nor allow_tags
# settings are enabled (or TO_JSON/FREEZE method missing) at
# /Users/bw/Documents/Dev/tests/json_perl_version_test.pl line 17.

# Hash2: {"something":"Wut?","v_quoted":"v5.34.0"}

请注意,没有必要引用 $item。

错误消息提到了一些处理其他情况的方法,但似乎不包括规范的 Perl 版本点分十进制字符串。我查看了主要的 Perl JSON 模块(JSON::MaybeXS、JSON 和 Cpanel::JSON::XS 的最新版本),但找不到任何引用 $^V 或点分十进制字符串的内容。也没有在 SO 上找到相关问题 :(。

也许我遗漏了什么?还是我坚持需要引用 $^V?

原因?

谢谢,

最佳答案

$^V variable真的是一个对象

The revision, version, and subversion of the Perl interpreter, represented as a version object.

对象不能就这样存储在 JSON 中。引用它会将其字符串化。


可以使 JSON::XS(及其 Cpanel::)成为一个有福的引用,但它涉及更多的工作。参见 Object Serialization .最干净的完整解决方案是 convert_blessed ,当 encode 方法将查找 TO_JSON 方法(在要添加到 JSON 的对象的类中)时,它将返回一个 JSON-ready 字符串。

唉,version 没有这样的东西(我试过的其他几个类也没有,比如 DateTime)。可以将该方法添加到类,但只要想到它就会使引号看起来不错。

另一种方法是明确地使 version 对象字符串化

my $json = JSON::XS->new->encode( { ver => $^V->stringify } )

这更加详细,但至少现在很清楚问题是什么,没有魔术引号。

或者只是引用它并添加评论。


例如,通过“猴子修补”

  • 添加具有完全限定名称的子

    perl -Mstrict -wE'use JSON::XS; say $^V; 
        sub version::TO_JSON { return $_[0]->stringify }; 
        my $json = JSON::XS->new->convert_blessed->encode( { ver => $^V } ); 
        say $json'
    

    也可以在运行时通过字符串 eval 添加一个 sub,但这似乎不需要。

  • 在运行时将代码引用写入类的符号表

    perl -wE'use JSON::XS; say $^V; 
        *{"version"."::"."TO_JSON"} = sub { return $_[0]->stringify }; 
        $json = JSON::XS->new->convert_blessed->encode( { ver => $^V } ); 
        say $json'
    

    好吧,或者真的在 strict 的情况下,我们需要允许符号引用

    perl -Mstrict -wE'use JSON::XS; say $^V; 
        NO_STRICT_REFS: { 
            no strict "refs"; 
            my ($class, $method) = qw(version TO_JSON);
            *{$class."::".$method} = sub { return $_[0]->stringify } 
        }; 
        my $json = JSON::XS->new->convert_blessed->encode( { ver => $^V } ); 
        say $json'
    

    我还为类名和方法添加了变量,这不是必需的但更好。

    这是为了在 Sub::Install 中更好地使用而打包的

    use Sub::Install;
    Sub::Install::install_sub({
        code => sub { ... }, into => $package, as => $subname
    });
    

    模块中有预期的默认值和更多内容。

或者,当然是通过编写包装类或类似的东西,但那是另外一回事。

关于json - 为什么JSON编码需要引用Perl版本字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70839513/

相关文章:

python - 我收到错误 _tkinter.TclError : bad window path name ".!button" and i'm not sure why

java - 知道为什么我的类(class)占用的内存比预期多得多吗?

json:无法将对象解码为 Auction.Item 类型的 Go 值

perl - 测试文件句柄中的可用数据

javascript - 如何创建一个扩展未预先确定的其他类的类

python - 根据列合并多个 CSV 文件

perl - 如何在 dd :mm:yyyy hh24:mi:ss format in descending order in Perl? 中对时间戳进行排序

javascript - axios响应请求返回一个奇怪的数组

PHP 将数组视为对象

Json 过滤同级节点上的数据