解除Perl对象的限制并为convert_构建TO_JSON方法
在中,我发现了一个简单的解除Perl对象的限制并为convert_构建TO_JSON方法,perl,moose,moo,Perl,Moose,Moo,在中,我发现了一个简单的TO_JSON方法的建议,它是将受祝福的对象序列化为JSON所必需的 sub TO_JSON { return { %{ shift() } }; } 有人能详细解释一下它是如何工作的吗 我把它改成: sub TO_JSON { my $self = shift; # the object itself – blessed ref print STDERR Dumper $self; my %h = %{
TO_JSON
方法的建议,它是将受祝福的对象序列化为JSON所必需的
sub TO_JSON { return { %{ shift() } }; }
有人能详细解释一下它是如何工作的吗
我把它改成:
sub TO_JSON {
my $self = shift; # the object itself – blessed ref
print STDERR Dumper $self;
my %h = %{ $self }; # Somehow unblesses $self. WHY???
print STDERR Dumper \%h; # same as $self, only unblessed
return { %h }; # Returns a hashref that contains a hash.
#return \%h; # Why not this? Works too…
}
许多问题…:(简单地说,我无法理解3行Perl代码(
我需要到_JSON
,但它会过滤掉:
- 不需要的属性和
- 也取消设置属性(例如,对于那些
谓词返回false的属性)具有${attr}
use 5.010;
use warnings;
use Data::Dumper;
package Some;
use Moo;
has $_ => ( is => 'rw', predicate => 1,) for (qw(a1 a2 nn xx));
sub TO_JSON {
my $self = shift;
my $href;
$href->{$_} = $self->$_ for( grep {!/xx/} keys %$self );
# Same mysterious unblessing. The `keys` automagically filters out
# “unset” attributes without the need of call of the has_${attr}
# predicate… WHY?
return $href;
}
package main;
use JSON;
use Data::Dumper;
my @objs = map { Some->new(a1 => "a1-$_", a2 => "a2-$_", xx=>"xx-$_") } (1..2);
my $data = {arr => \@objs};
#say Dumper $data;
say JSON->new->allow_blessed->convert_blessed->utf8->pretty->encode($data);
编辑:澄清问题:
解除了%{$hRef}
的限制(获取引用指向的哈希),但是为什么要从受祝福的对象引用$hRef
获取普通哈希呢$self
- 换句话说,为什么
是hashref$self
- 我试着制作一个像
这样的散列片,但它不起作用。因此我创建了一个可怕的@{$self}{grep{!/xx/}keys%$self}
来处理JSON
- 如果
是一个hashref,为什么$self
只返回具有值的属性,而不是所有声明的属性(例如键%$self
也–请参见nn
)has
在您的
TO_JSON()
函数中,{%h}
返回一个浅哈希副本,而\%h
返回一个对%h
的引用(无复制)。Perl实现的面向对象方法是简单地让引用知道它来自哪个包(使用bless
).知道引用来自Foo
包意味着方法实际上是该包中定义的函数
Perl允许任何类型的引用被祝福;不仅仅是散列引用。祝福散列引用是很常见的;很多文档都显示了这一点;Moose
做到了;但是,祝福数组引用、子例程引用、文件句柄或标量引用也是可能的tax%{$self}
仅对哈希引用(受祝福或不受祝福)有效。它接受哈希引用,并将其作为哈希解引用。原始引用可能已受祝福的事实将丢失
我需要TO_JSON,但会过滤掉什么:
- 不需要的属性
- 以及unset属性(例如,对于那些has${attr}谓词返回false的属性)
undef
值和键,那么有几个选项。下面是我使用模块得到的:
map
s和grep
s并不一定漂亮,但这是我能想到的过滤掉不在白名单上的键和没有undef
值的元素的最简单方法
您可以使用数组切片:
use strict;
use warnings;
use JSON;
my $foo = { foo => undef, bar => 'baz', quux => 5 };
my @whitelist = qw{foo bar};
my %filtered_on_keys;
@filtered_on_keys{@whitelist} = @$foo{@whitelist};
my %bar = map { $_ => $filtered_on_keys{$_} }
grep { defined $filtered_on_keys{$_} }
keys %filtered_on_keys;
print to_json(\%bar) . "\n";
或者,如果您喜欢循环:
use strict;
use warnings;
use JSON;
my $foo = { foo => undef, bar => 'baz', quux => 5 };
my %whitelist = map { $_ => 1 } qw{foo bar};
my %bar;
while (my ($key, $value) = each %$foo) {
if (defined $value && exists $whitelist{$key}) {
$bar{$key} = $value;
}
}
print to_json(\%bar) . "\n";
这似乎是一个很好的时间来提出拉里·沃尔的话,“Perl旨在给你几种方法做任何事情,所以考虑挑选最可读的。”
但是,我强调了一点,即并非所有对象都是散列。从对象获取数据的适当方法是通过其getter函数:
use strict;
use warnings;
use JSON;
my $foo = Foo->new({ foo => undef, bar => 'baz', quux => 5 }); # as an example
my %filtered_on_keys;
@filtered_on_keys{qw{foo bar}} = ($foo->get_foo(), $foo->get_bar());
my %bar = map { $_ => $filtered_on_keys{$_} }
grep { defined $filtered_on_keys{$_} }
keys %filtered_on_keys;
print to_json(\%bar) . "\n";
Thanx为您的答案-我编辑了我的问题(我希望)更清楚。无论如何,+1因为返回{%hash}的
浅哈希副本对我来说是新的,需要搜索一些关于它的文档。;)接受这个答案,因为你帮了我处理切片和“浅哈希副本”;)-应在其他问题中提出与Moo相关的问题。请注意::)第二和第四个问题与moose相关(perl OO主要使用hashref进行对象存储)。哈希片只返回值,如果我是正确的,您需要键/值对。my%h=map{$\=>$self->{$\}}grep{!/xx/}键%$self
或my%h=%$self;删除@h{grep/xx/,key%$self}
@mpapec-THANX,你的评论帮我找到了一个bug。我有Perl5.20,因此可以使用返回{%{$self}{grep{!/xx/}键%$self}代码>-它最终工作:)(键/值哈希片)。问题出现在第一个信号@
中。在这种形式下,它实际上返回一个值。:)很高兴有你
use strict;
use warnings;
use JSON;
my $foo = { foo => undef, bar => 'baz', quux => 5 };
my %whitelist = map { $_ => 1 } qw{foo bar};
my %bar;
while (my ($key, $value) = each %$foo) {
if (defined $value && exists $whitelist{$key}) {
$bar{$key} = $value;
}
}
print to_json(\%bar) . "\n";
use strict;
use warnings;
use JSON;
my $foo = Foo->new({ foo => undef, bar => 'baz', quux => 5 }); # as an example
my %filtered_on_keys;
@filtered_on_keys{qw{foo bar}} = ($foo->get_foo(), $foo->get_bar());
my %bar = map { $_ => $filtered_on_keys{$_} }
grep { defined $filtered_on_keys{$_} }
keys %filtered_on_keys;
print to_json(\%bar) . "\n";