2013-04-25 130 views
3

我有一個任意的數據結構,我想把它作爲一個對象。我將此作爲REST應用程序的響應。下面的例子。 CPAN上有一些模塊承諾可以做到這一點。 Data :: Object對我來說看起來最好,但是它最後更新了2011年。我錯過了什麼嗎?有沒有一種簡單的駝鹿方式來做到這一點?謝謝!將數據結構轉換爲perl對象(模塊推薦)

$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' 
}; 
+0

如果它是任意的,你爲什麼要把它當作一個對象來對待? – ysth 2013-04-26 17:27:35

+0

你試過Data :: Object嗎?它沒有工作嗎?一目瞭然,Data :: Object是簡單的Moose方法... – RickF 2013-04-29 16:04:56

回答

0

這是一個例子:

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 
0

我不是說這一定是一個好主意,做的想法,或免費的疑難雜症,最好的方式。我從來沒有嘗試過,直到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, $/; 
1

雖然我不喜歡使用它,定義AUTOLOAD子程序是一種能夠在飛行中創建任意類。它已經有一段時間,因爲我用它,但它應該是這個樣子:

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; isn'噸有效的方法

一個小問題:。。一旦你定義一個AUTOLOAD函數,你也可以定義DESTROY子程序太多的Perl調用DESTROY子程序的對象被銷燬之前,您需要處理的問題,如果$AUTOLOAD =~ /.*::DESTROY$/,那麼也可以需要補充:

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

某處在AUTOLOAD子程序中,所以你沒有意識到當調用DESTROY時,會做點什麼。請記住,只要類對象超出範圍,就會自動調用該對象,如果存在,則使用AUTOLOAD,您仍然定義了一個。

+0

'my($ self,$ value)= @_; ... $ self - > {$ method} = $ value if __> 1; ...或者至少是$ self - > {$ method} = $ value,如果定義了$ value;'。 (另請注意,我的($ self,$ value)= @ _'將在5.18及更高版本中轉換爲單個操作) – 2013-04-26 17:06:05

+0

我通常喜歡在子例程中分配變量時使用'shift',而不是簡單地說'my $ self,$ value)= @_;'因爲它更容易看到作業。無論哪種方式將工作。如果定義了$ value,你對'$ self - > {$ method} = $ value是正確的,因爲如果$ value是零或者一個空字符串,它就不會被設置。我通常使用一個完整的'if'並且這樣做。我會改變我的答案。 – 2013-04-26 17:23:04