我一直在尝试找到一个Perl模块,它将YAML文件转换为moose对象,而不必像使用MooseX::YAML时那样预先声明结构。有谁知道这样的模块(或脚本)?
答案 0 :(得分:7)
别。
Moose类,它们的属性以及属于它们的任何其他内容都附带了大量的元数据。您无法从单个实例的数据中推断出所有元数据。
我假设,给出一个yaml文件
---
foo: 42
bar: ['moo', 'kooh']
您期望并反对回复对foo
和bar
方法的调用,并返回相应的值。但那些访问者应该如何表现呢?它们应该是简单的读者方法,还是允许写作?他们应该验证任何类型的typeconstraint吗?等
如果您真正需要的是使某些未经处理的数据结构像对象一样可访问的内容,请查看Data::Hive
,Hash::AsObject
和类似的模块。
如果你真的想要构建适当的Moose类,并且要么参与其中的猜测,或者碰巧在某处可以获得必要的元数据,那么你可以使用元协议。
my $class = Moose::Meta::Class->create_anon_class(
attributes => [map {
# your particular set of assumptions here
Moose::Meta::Attribute->new($_ => (is => 'ro', ...))
} keys %{ $deserialized_yaml }],
);
my $instance = $class->name->new($deserialized_yaml);
$instance->$some_key_in_the_yaml_document;
答案 1 :(得分:3)
如果你不想在YAML中做任何特别的事情,你可以设置
适当强制你的Moose类,然后将加载的数据传递给
new()
。例如:
package My::Types;
use Moose::Util::TypeConstraints;
class_type 'My::Related::Class';
coerce 'My::Related::Class', from 'HashRef',
via { My::Related::Class->new(%$_) };
package My::Class;
use Moose;
has name => (is => 'ro', isa => 'Str');
has related => (is => 'ro', isa => 'My::Related::Class', coerce => 1);
package My::Related::Class;
use Moose;
has flavor => (is => 'ro', isa => 'Str');
然后,在某些YAML中:
name: "An instance of My::Class"
related:
flavor: "Dangerberry!"
然后,在某些代码中:
my $obj = My::Class->new(Load($yaml_data));
print ref $obj->related; # My::Related::Class
print $obj->related->flavor; # Dangerberry!
这显然不是圆形的,没有更多的Moose类定制 - 它只是用于构造对象。此外,您需要知道根对象是什么类。
但这对于很多简单的用途来说已经足够了。