是否可以从数据结构生成 Moose 类定义(perl 源)?存在这样的CPAN模块吗?
是的。但是,您如何做到这一点将在很大程度上取决于您希望完成的任务。最简单的方法是在基于 JSON 的内存中构建属性。例如,您可以在运行时从 JSON 文件中实例化元类对象,如下所示:
sub infer_class_from_hash {
my ($input) = @_;
# Makes for ugly class names, but does the job
my $meta = Moose::Meta::Class->create_anon_class;
for my $key (keys %$input) {
my $value = $input->{$key};
my $type;
my $coerce = 0;
# Handle nested objects in the JSON as Moose objects
if (ref $value eq 'HASH') {
my $inner_meta = infer_class_from_hash($value);
$type = $meta->name;
# We provide an automatic HASH -> Class coercion
$coerce = 1;
}
# Assume arrays are always of scalars, could be extended to handle objects
elsif (ref $value eq 'ARRAY') {
$type = 'ArrayRef',
}
# Assume anything else is string-ish
else {
$type = 'Str',
}
$meta->add_attribute($key =>
is => 'rw',
isa => $type,
coerce => $coerce,
);
}
# Create a coercion that makes instantiating from the JSON tree dead simple
use Moose::Util::TypeConstraints;
coerce $meta->name => from 'HashRef' => via { $meta->name->new($_) };
no Moose::Util::TypeConstraints;
return $meta;
}
所有这一切甚至还没有开始进入你可以做的事情。您可以应用角色、自定义基类、添加方法等。但是,这是动态构建 Moose 类的基础。
如果你想要一个代码生成器,将实际的 Moose 类输出为可以构建一次然后加载的文件,那么你可以做任何你想做的事情。我只是编写一个与上面类似的程序,但输出一组.pm
文件,其中包含自动生成的 Moose 类定义。
当我得到类层次结构时(例如,如果这里没有任何帮助,我可以手动编写它们),从 JSON 创建(初始化)它们的实例的最简单方法是什么?
use JSON qw( from_json );
my $hash = from_json("...");
my $meta = infer_class_from_hash($hash);
my $obj = $meta->name->new($hash);
The key here is how we use Moose type coercion to automatically convert the JSON objects read in into Moose class instances. If you have more than one serialization scheme or want to use type constraints in some other way, you could setup a base class for all of these (in the call to create_anon_class
) that provided to_json
/from_json
methods to handle the case of nested objects in the JSON input.