I have a class, 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 } };
}
Currently when I instantiate MyClass and pass the new object to the json_encoder I get a JSON string returned as expected. I was hoping that the perl booleans ( 1,0 ) would be converted to ( true, false ) but that is not how the JSON module is designed:
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 );
In MyClass, I want to improve my TO_JSON subroutine to provide a conversion of any Moose 'Bool' member from ( 1 or 0 ) to ( true or 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
}
}
}
How can I determine the Moose Type as I iterate through MyClass' members so I can provide a mechanism for the conversion?
Here's one way to do it:
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
We use the metaclass object (accessible via ->meta
) to introspect the class and get a list of all attributes (in the form of meta-attribute objects).
For each attribute, we get the name, current value, and type constraint (if any). If the type is Bool
, we convert the value to either \1
or \0
. The JSON module understands these values and converts them to true
or false
.
And a test program:
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";
Output:
Result: {"IntegerMember":10,"BooleanMember":true}