我在文件Point.pm
中定义了一个Point对象,如下所示:
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;
现在,当我使用JSON通过以下代码将对象转换为JSON时:
use JSON;
use Point;
Point $p = new Point;
$p->X(20);
$p->Y(30);
my $json = encode_json $p;
我收到以下错误:
encountered object 'Point=HASH(0x40017288)', but neither allow_blessed nor convert_blessed settings are enabled at test.pl line 28
如何使用JSON模块将JSON转换为对象?
答案 0 :(得分:21)
警告告诉你大部分错误。除非你告诉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() } }; }
如果你必须下降一个结构,它将获得 lot 发型。
下面评论中有人说我没有介绍如何获取JSON的对象 out 。
基础很简单。所以这里是
my $object = bless( JSON->new->decode( $json_string ), 'ClassIWant' );
我主要介绍阻止你只需将祝福的对象序列化为JSON的部分。
反序列化的基础很简单,就像序列化的基础知识一样简单 - 一旦你知道了这个技巧。顺便说一句,没有任何错误,只需要找到你需要的东西,并把它祝福到正确的班级。
如果你想让代码与对象相结合,那么你就会知道什么是有福的,以及它必须被祝福的东西。如果你想要完全解耦的代码,这在Perl中并不比在JavaScript本身中更难或更容易。
您将不得不在JSON中序列化标记。如果我需要这样的东西,我会在祝福的物体中插入一个'__CLASS__'
字段。当反序列化时,我将通过结构下降并祝福这样的一切:
bless( $ref, delete $ref->{__CLASS__} );
但正如我所说,这在Perl中并不容易或者更难,因为JSON对所有语言都提出了同样的挑战。
正如Schwern在他的评论中提出的那样,YAML更适合序列化和反序列化对象,因为它有符号。 JSON为您提供关联数组或数组。
答案 1 :(得分:5)
您是否尝试按照错误消息的建议阅读JSON documentation和allow_blessed选项中的convert_blessed?这应该解释如何将Perl对象转换为JSON。
另一种方式更难,因为JSON不是YAML,并且没有被设计为反序列化为像Perl这样的基于类的对象系统。您可以尝试使用filter_json_object或filter_json_single_key_object选项,也可以对已解码的JSON进行后期处理并自行创建对象。
答案 2 :(得分:3)
您需要JSYNC。
use JSYNC;
use Point;
my $p = Point->new;
$p->X(20);
$p->Y(30);
my $jsync = JSYNC::dump($p, {pretty => 1});
{
"!" : "!perl/hash:Point",
"_x" : "20",
"_y" : "30"
}
答案 3 :(得分:2)
您可能会发现将类转换为Moose并使用MooseX::Storage对其进行序列化和反序列化非常有用。