Существует ли модуль Perl для динамического преобразования файлов YAML в объекты Moose во время выполнения? - PullRequest
4 голосов
/ 16 октября 2010

Я пытался найти модуль Perl, который преобразует YAML-файл в объекты Moose, без необходимости предварительно объявлять структуру, как вам, вероятно, требуется при использовании MooseX :: YAML . Кто-нибудь знает о таком модуле (или скрипте)?

Ответы [ 2 ]

7 голосов
/ 16 октября 2010

Не.

Классы лося, их атрибуты и все, что к ним принадлежит, имеют множество метаданных, прикрепленных к ним.Вы не можете вывести все эти метаданные из данных одного экземпляра.

Я предполагаю, что для документа yaml указано

---
foo: 42
bar: ['moo', 'kooh']

, которое вы ожидаете, и объектобратно, который отвечает на вызовы методов foo и bar, возвращая соответствующие значения.Но как должны вести себя эти средства доступа?Должны ли они быть простыми методами чтения или также позволять писать?Должны ли они проверять против какого-либо типа ограничения?и т. д.

Если все, что вам действительно нужно, это что-то, что делает некоторую необъясненную структуру данных доступной, например, объект, взгляните на 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;
3 голосов
/ 16 октября 2010

Если вы не хотите делать что-то особенное в вашем 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 - это просто для создания объектов. Также вам необходимо знать, какие классы являются корневыми объектами.

Впрочем, этого вполне достаточно для простого использования.

...