2023-11-10 20:30:25 +00:00
|
|
|
use 5.38.0;
|
|
|
|
|
2023-11-14 16:45:06 +00:00
|
|
|
=head1 DESCRIPTION
|
|
|
|
|
|
|
|
Serializer for JSON:API. Takes in a data structure, munge it to conforms to the JSON:API format (potentially based on a provided registry of JSON:API schemas),
|
|
|
|
and encode it as JSON.
|
|
|
|
|
|
|
|
Note that using Dancer2::Plugin::JsonApi in an app will automatically
|
|
|
|
set C<Dancer2::Serializer::JsonApi> as its serializer if it's not already defined.
|
|
|
|
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
|
|
|
|
As part of a Dancer2 App:
|
|
|
|
|
|
|
|
# in config.yaml
|
|
|
|
|
|
|
|
serializer: JsonApi
|
|
|
|
|
|
|
|
As a standalone module:
|
|
|
|
|
|
|
|
use Dancer2::Serializer::JsonApi;
|
|
|
|
use Dancer2::Plugin::JsonApi::Registry;
|
|
|
|
|
|
|
|
my $registry = Dancer2::Plugin::JsonApi::Registry->new;
|
|
|
|
|
|
|
|
$registry->add_type( 'spaceship' => {
|
|
|
|
relationships => {
|
|
|
|
crew => { type => 'person' }
|
|
|
|
}
|
|
|
|
} );
|
|
|
|
|
|
|
|
$registry->add_type( 'person' );
|
|
|
|
|
|
|
|
my $serializer = Dancer2::Serializer::JsonApi->new(
|
|
|
|
registry => $registry
|
|
|
|
);
|
|
|
|
|
|
|
|
my $serialized = $serializer->serialize([
|
|
|
|
'spaceship', {
|
|
|
|
id => 1,
|
|
|
|
name => 'Unrequited Retribution',
|
|
|
|
crew => [
|
|
|
|
{ id => 2, name => 'One-eye Flanagan', species => 'human' },
|
|
|
|
{ id => 3, name => 'Flabgor', species => 'Moisterian' },
|
|
|
|
]
|
|
|
|
}
|
|
|
|
]);
|
|
|
|
|
|
|
|
=cut
|
|
|
|
|
2023-11-10 20:30:25 +00:00
|
|
|
package Dancer2::Serializer::JsonApi;
|
|
|
|
|
|
|
|
use Dancer2::Plugin::JsonApi::Registry;
|
|
|
|
use Dancer2::Serializer::JSON;
|
|
|
|
|
|
|
|
use Moo;
|
|
|
|
|
2023-11-14 16:45:06 +00:00
|
|
|
=head1 ATTRIBUTES
|
|
|
|
|
|
|
|
=head2 content_type
|
|
|
|
|
|
|
|
Returns the content type used by the serializer, which is C<application/vnd.api+json>;
|
|
|
|
|
|
|
|
=cut
|
|
|
|
|
2023-11-10 20:30:25 +00:00
|
|
|
has content_type => ( is => 'ro', default => 'application/vnd.api+json' );
|
|
|
|
|
|
|
|
with 'Dancer2::Core::Role::Serializer';
|
|
|
|
|
2023-11-14 16:45:06 +00:00
|
|
|
=head2 registry
|
|
|
|
|
|
|
|
The L<Dancer2::Plugin::JsonApi::Registry> to use.
|
|
|
|
|
|
|
|
=cut
|
|
|
|
|
2023-11-10 20:30:25 +00:00
|
|
|
has registry => (
|
|
|
|
is => 'rw',
|
|
|
|
default => sub { Dancer2::Plugin::JsonApi::Registry->new }
|
|
|
|
);
|
|
|
|
|
2023-11-14 16:45:06 +00:00
|
|
|
=head2 json_serializer
|
|
|
|
|
|
|
|
The underlying JSON serializer. Defaults to L<Dancer2::Serializer::JSON>.
|
|
|
|
|
|
|
|
=cut
|
|
|
|
|
2023-11-10 20:30:25 +00:00
|
|
|
has json_serializer => (
|
|
|
|
is => 'ro',
|
|
|
|
default => sub { Dancer2::Serializer::JSON->new }
|
|
|
|
);
|
|
|
|
|
2023-11-14 16:45:06 +00:00
|
|
|
=head1 METHODS
|
|
|
|
|
|
|
|
=head2 $self->serialize( [ $type, $data, $xtra ])
|
|
|
|
|
|
|
|
Serializes the C<$data> using the C<$type> from the registry.
|
|
|
|
The returned value will be a JSON string.
|
|
|
|
|
|
|
|
=cut
|
|
|
|
|
2023-11-10 20:30:25 +00:00
|
|
|
sub serialize {
|
|
|
|
my ( $self, $data ) = @_;
|
|
|
|
|
|
|
|
return $self->json_serializer->serialize(
|
2023-11-12 18:23:01 +00:00
|
|
|
$self->registry->serialize(@$data) );
|
2023-11-10 20:30:25 +00:00
|
|
|
}
|
|
|
|
|
2023-11-14 16:45:06 +00:00
|
|
|
=head2 $self->deserialize( $json_string )
|
|
|
|
|
|
|
|
Takes in the serialized C<$json_string> and recreate data out of it.
|
|
|
|
|
|
|
|
=cut
|
|
|
|
|
2023-11-15 18:25:43 +00:00
|
|
|
sub deserialize ( $self, $serialized, @ ) {
|
|
|
|
$self->registry->deserialize(
|
|
|
|
$self->json_serializer->deserialize($serialized) );
|
|
|
|
}
|
2023-11-10 20:30:25 +00:00
|
|
|
|
|
|
|
1;
|