【问题标题】:Determine the Moose Type for providing conversion to JSON确定提供 JSON 转换的 Moose 类型
【发布时间】:2017-11-02 14:09:31
【问题描述】:

我有一个班级,MyClass:

package MyClass;
use Moose;

has 'IntegerMember' => (
    is => 'rw',
    isa => 'Int'
);

has 'BooleanMember' => (
    is => 'rw',
    isa => 'Bool'
);

sub TO_JSON {
    my $self = shift;
    return { % { $self } };
}

目前,当我实例化 MyClass 并将新对象传递给 json_encoder 时,我得到了一个按预期返回的 JSON 字符串。我希望将 perl 布尔值( 1,0 )转换为( true, false ),但这不是 JSON 模块的设计方式:

use JSON;
use MyClass;

my $object_to_encode = MyClass->new ( 
    IntegerMember => 10,
    BooleanMember => 1
);
my $json_encoder = JSON->new->convert_blessed;
my $json_data = $json_encoder->encode( $object_to_encode );

在 MyClass 中,我想改进我的 TO_JSON 子例程,以提供任何 Moose 'Bool' 成员从(1 或 0)到(true 或 false)的转换:

sub TO_JSON {
    my $self = shift;
    for my $member ( %$self ) {
        if {
            # Convert '1' to 'true' if Moose Type is 'Bool'
        } else {
            # Keep the member as is
        }
    }
}

当我遍历 MyClass 的成员时,如何确定 Moose 类型,以便为转换提供机制?

【问题讨论】:

  • JSON 模块将 truefalse 表示为标量引用 \1\0。但它不知道 12 是布尔值。
  • 您需要致电$json_encoder->encode。这是一个对象。
  • 另外,这不是 Moose 中的 isa 所做的。它并不真正关心 type 本身,因为 Perl(或 Moose)中没有类型。您放入 isa 的内容仅用于运行时检查您放入属性的内容。
  • 而且你不应该直接干预底层$self 的内部结构。事实上,您的 for 循环只会迭代一次,因为 $self 是一个哈希引用。所以你有一个元素的列表。该元素是$self。它将分配给$member,然后您就完成了。但也有语法错误,因为for 块不能有else 块。我认为您需要重新考虑您要完成的工作。
  • 谢谢辛巴克。我已经更正了你提到的我忽略的语法错误。

标签: json perl introspection moose


【解决方案1】:

这是一种方法:

package MyClass;
use Moose;

has 'IntegerMember' => (
    is => 'rw',
    isa => 'Int'
);

has 'BooleanMember' => (
    is => 'rw',
    isa => 'Bool'
);

sub TO_JSON {
    my $self = shift;
    my $meta = $self->meta;
    my $result = {};
    for my $attr ($meta->get_all_attributes) {
        my $name = $attr->name;
        my $value = $attr->get_value($self);
        my $type = $attr->type_constraint;
        if ($type && $type->equals('Bool')) {
            $value = $value ? \1 : \ 0;
        }
        $result->{$name} = $value;
    }
    return $result;
}

1

我们使用metaclass object(可通过->meta访问)来内省类并获取所有属性的列表(以meta-attribute objects的形式)。

对于每个属性,我们获取名称、当前值和type constraint(如果有)。如果类型是Bool,我们将值转换为\1\0。 JSON 模块理解这些值并将它们转换为truefalse

还有一个测试程序:

use strict;
use warnings;
use JSON::MaybeXS;
use MyClass;

my $object_to_encode = MyClass->new ( 
    IntegerMember => 10,
    BooleanMember => 1
);
my $json_encoder = JSON->new->convert_blessed;
my $json_data = $json_encoder->encode( $object_to_encode );

print "Result: $json_data\n";

输出:

Result: {"IntegerMember":10,"BooleanMember":true}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多