如何将Perl对象转换为JSON,反之亦然

Ibr*_*him 21 perl json

我在文件中定义了一个Point对象,Point.pm如下所示:

package Point;
sub new {
    my ($class) = @_;
    my $self = {
        _x => 0,
        _y => 0,
    };
    return bless $self => $class;
}

sub X {
    my ($self, $x) = @_;
    $self->{_x} = $x if defined $x;
    return $self->{_x};
}

sub Y {
    my ($self, $y) = @_;
    $self->{_y} = $y if defined $y;
    return $self->{_y};
}

1;
Run Code Online (Sandbox Code Playgroud)

现在,当我使用JSON通过以下代码将对象转换为JSON时:

use JSON;
use Point;

Point $p = new Point;
$p->X(20);
$p->Y(30);

my $json = encode_json $p;
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

encountered object 'Point=HASH(0x40017288)', but neither allow_blessed nor convert_blessed settings are enabled at test.pl line 28
Run Code Online (Sandbox Code Playgroud)

如何使用JSON模块将JSON转换为对象?

Axe*_*man 22

警告告诉你大部分错误.除非你告诉JSON如何处理有福的引用(Perl对象),否则JSON只处理未受祝福的数据结构.

你可以convert_blessed,你可以allow_blessed.因为allow_blessed,它说:

如果$enable为false(默认值),则encode在遇到祝福对象时将抛出异常.

Point是一个对象类,因此一个实例Point是一个有福的引用,因此默认为JSON抛出一个异常.

如果启用convert_blessed,它将调用TO_JSON对象上的方法.对于简单的对象Point(包含没有祝福成员的对象),您可以像以下一样轻松地执行此操作:

sub TO_JSON { return { %{ shift() } }; }
Run Code Online (Sandbox Code Playgroud)

如果你有一个下降的结构,它会得到很多的多毛.


下面评论中有人说我没有介绍如何 JSON中获取对象.

基础很简单.所以这里

my $object = bless( JSON->new->decode( $json_string ), 'ClassIWant' );
Run Code Online (Sandbox Code Playgroud)

我主要介绍了阻止您简单地将祝福对象序列化为JSON的部分.

反序列化的基础很简单,就像序列化的基础知识一样简单 - 一旦你知道了这个技巧.顺便说一句,没有任何错误,只需要找到你需要的东西,并把它祝福到正确的班级.

如果你想让代码与对象相结合,那么你就会知道必须得到什么祝福以及它必须得到什么才能得到祝福.如果你想要完全解耦的代码,这在Perl中比在JavaScript本身中更难或更容易.

您将不得不在JSON中序列化标记.如果我需要这样的东西,我会'__CLASS__'在祝福的物体中插入一个字段.当反序列化时,我将通过结构下降并祝福这样的一切:

 bless( $ref, delete $ref->{__CLASS__} );
Run Code Online (Sandbox Code Playgroud)

但正如我所说,这在Perl中并不容易或者更难,因为JSON对所有语言都提出了同样的挑战.

正如Schwern在他的评论中提出的那样,YAML更适合于序列化和反序列化对象,因为它有它的符号.JSON为您提供关联数组或数组.

  • 或者:to_json($ blessed_object,{allow_blessed => 1,convert_blessed => 1}) (4认同)

cjm*_*cjm 5

您是否尝试按照错误消息的建议阅读allow_blessedconvert_blessed选项上的JSON文档?这应该解释如何将Perl对象转换为JSON.

另一种方式更难,因为JSON不是YAML,并且不是被设计为反序列化为像Perl这样的基于类的对象系统.您可以尝试使用filter_json_objectfilter_json_single_key_object选项,也可以对已解码的JSON进行后处理并自行创建对象.


dax*_*xim 5

你需要JSYNC

use JSYNC;
use Point;
my $p = Point->new;
$p->X(20);
$p->Y(30);

my $jsync = JSYNC::dump($p, {pretty => 1});
Run Code Online (Sandbox Code Playgroud)
{
   "!" : "!perl/hash:Point",
   "_x" : "20",
   "_y" : "30"
}
Run Code Online (Sandbox Code Playgroud)