将数据结构转换为perl对象(模块建议)

将数据结构转换为perl对象(模块建议),perl,object,moose,Perl,Object,Moose,我有一个任意的数据结构,我想把它当作一个对象。我从一个REST应用程序得到这个响应。下面的例子。CPAN上有一些模块承诺这样做。Data::Object在我看来是最好的,但它最近一次更新是在2011年。我错过什么了吗?也许有一种简单的驼鹿方法可以做到这一点吗?谢谢 $o=$class->new($response); $s=$o->success; @i=$o->items; { 'success' => bless( do{\(my $o = 1)}, 'JSO

我有一个任意的数据结构,我想把它当作一个对象。我从一个REST应用程序得到这个响应。下面的例子。CPAN上有一些模块承诺这样做。Data::Object在我看来是最好的,但它最近一次更新是在2011年。我错过什么了吗?也许有一种简单的驼鹿方法可以做到这一点吗?谢谢

$o=$class->new($response);
$s=$o->success;
@i=$o->items;
{
    'success' => bless( do{\(my $o = 1)}, 'JSON::XS::Boolean' ),
    'requestNumber' => 5,
    'itemsCount' => 1,
    'action' => 'search.json',
    'totalResults' => 161,
    'items' => [
        {
            'link' => 'http://europeana.eu/api//v2/record/15503/E627F23EF13FA8E6584AF8706A95DB85908413BE.json?wskey=NpXXXX',
            'provider' => [
                'Kulturpool'
            ],
            'europeanaCollectionName' => [
                '15503_Ag_AT_Kulturpool_khm_fs'
            ],
            # more fields omitted
        }
    ],
    'apikey' => 'Npxxxx'
}; 
这是一个例子:

use strict;

package Foo; 

#define a simple Foo class with 3 properties
use base qw(Class::Accessor);
Foo->mk_accessors(qw(name role salary));


package main;
#define a perl hash with the same keys
my $hr = {'name'=>'john doe', 'role'=>'admin', 'salary'=>2500 };

#bless the object
my $obj = bless $hr, 'Foo';

print $obj->name, "\n"; #<-- prints: john doe
使用严格;
包装食品;
#定义一个具有3个属性的简单Foo类
使用基本qw(类::访问器);
Foo->mk_访问者(qw(姓名-角色-薪资));
主包装;
#使用相同的键定义perl哈希
我的$hr={'name'=>'johndoe','role'=>'admin','salary'=>2500};
#祝福这个物体
我的$obj=祝福$hr,‘Foo’;

打印$obj->name,“\n”# 我并不是说这一定是一个好主意,这是实现这个想法的最佳方式,或者说是免费的。直到15分钟前我才试过。但这很有趣,也很简洁,所以——

#!/usr/bin/env perl
BEGIN {
    package Role::AutoVacca;
    use Moo::Role;
    use Scalar::Util "blessed";
    sub BUILD {
        my $self = shift;
        for my $attr ( grep /\A[^_]/, keys %{$self} )
        {
            Method::Generate::Accessor
                ->generate_method( blessed($self),
                                   $attr,
                                   { is => "rw" } );
        }
    }

    package Fakey;
    use Moo;
    with "Role::AutoVacca";
}

my $fake = Fakey->new({
    success => bless( do{\(my $o = 1)}, "JSON::XS::Boolean" ),
    items => [ { link => "http://europeana.eu/o/haipi",
                 provider => [ "mememememe" ] } ],
    apikey => "3k437" });

print "I CAN HAZ KEE? ", $fake->apikey, $/;
print "IZ GUD? ", $fake->success ? "YAH" : "ONOES", $/;
print "WUT DIZZYING? ", $fake->items, $/;

尽管我不喜欢使用它,但定义
自动加载
子例程是一种动态创建任意类的方法。我已经有一段时间没用了,但它应该是这样的:

package Local::Foo;

sub new {
    my $class = shift;

    my $self = {};
    bless $self, $class;
    return $self;
}

sub AUTOLOAD {
    my $self = shift;
    my $value = shift;

    our $AUTOLOAD;
    (my $method = $AUTOLOAD) = s/.*:://;
    if ( defined $value ) {
        $self->{$method} = $value;
    }
    return $self->{$method};
}
这个类
Local::Foo
有无限多的方法。例如,如果我说

$foo->bar("fubar");
这与:

$foo->{bar} = "foobar";
如果我调用
$foo->bar
,它将返回
$foo->{bar}的值

您可能想要一些东西来限制方法的样式及其值。例如:

$foo->BAR;
$foo->Bar;
$foo->bar;
这三种方法都是有效且完全不同的。您可能需要一些东西来确保您的方法匹配特定的模式(即,它们都是小写的,或者第一个字母是大写的,其余的是小写的)。您可能需要确保它们以字母开头,因此,
$foo->23diba;
不是有效的方法

一个小问题:定义了
自动加载
子例程之后,也定义了
销毁
子例程。在销毁对象之前,Perl调用了
销毁
子例程。如果
$AUTOLOAD=~/.*::DESTROY$/
也需要处理此问题。您可能需要添加:

return if $AUTOLOAD =~ /.*::DESTROY$/;

自动加载
子例程中的某个地方,这样在调用
销毁
时不会意外地执行某些操作。请记住,只要类对象不在范围内(如果存在),就会自动调用它,并且使用
自动加载
,您已经定义了一个。

关于
我的($self,$value)=@;$self->{$method}=$value if@>1;..
或至少
$self->{$method}=$value if defined$value;
(还请注意,
my($self,$value)=@
将在5.18及更高版本中转换为单个运算)我通常喜欢在子例程中指定变量时使用
shift
,而不是简单地说
my($self,$value)=@;
因为这样更容易看到作业。任何一种方法都可以。关于
$self->{$method}你是对的=$value如果定义了$value
,因为如果$value是零或空字符串,它就不会被设置。我通常使用完整的
如果
,然后这样做。我会更改我的答案。如果是任意的,为什么要将其视为对象?你尝试过Data::object吗?它不起作用吗?乍一看,Data::object是一种简单的Moose方式来做。。。