Dancer::Serializer::Mutable - (De)Serialize content using the appropriate HTTP header


Dancer documentation Contained in the Dancer distribution.

Index


Code Index:

NAME

Top

Dancer::Serializer::Mutable - (De)Serialize content using the appropriate HTTP header

SYNOPSIS

Top

DESCRIPTION

Top

This serializer will try find the best (de)serializer for a given request. For this, it will go through:

The content_type from the request headers

the content_type parameter from the URL

the accept from the request headers

The default is application/json

METHODS

serialize

Serialize a data structure. The format it is serialized to is determined automatically as described above. It can be one of YAML, XML, JSON, defaulting to JSON if there's no clear preference from the request.

deserialize

Deserialize the provided serialized data to a data structure. The type of serialization format depends on the request's content-type. For now, it can be one of YAML, XML, JSON.

content_type

Returns the content-type that was used during the last serialize / deserialize call. WARNING : you must call serialize / deserialize before calling content_type. Otherwise the return value will be undef.


Dancer documentation Contained in the Dancer distribution.

package Dancer::Serializer::Mutable;

use strict;
use warnings;

use base 'Dancer::Serializer::Abstract';
use Dancer::SharedData;

my $serializer = {
    'text/x-yaml'      => 'YAML',
    'text/html'        => 'YAML',
    'text/xml'         => 'XML',
    'text/x-json'      => 'JSON',
    'application/json' => 'JSON',
};

my $loaded_serializer = {};
my $_content_type;

sub _find_content_type {
    my ($self, $request) = @_;

    # first content type, second accept and final default
    my %content_types;
    my $params;

    if ($request) {
        $params = $request->params;
    }

    my $method = $request->method;

    if ($method =~ /^(?:POST|PUT)$/) {
        if ($request->{content_type}) {
            $content_types{$request->{content_type}} = 4;
        }

        if ($params && $params->{content_type}) {
            $content_types{$params->{content_type}} = 3;
        }
    }

    if ($request->{accept}) {
        $content_types{$request->{accept}} = 2;
    }
    if ($request->{'accept_type'}) {
        $content_types{$request->{accept_type}} = 1;
    }

    $content_types{'application/json'} = 0
      unless defined $content_types{'application/json'};

    return [
        sort { $content_types{$b} <=> $content_types{$a} }
          keys %content_types
    ];
}

sub serialize {
    my ($self, $entity) = @_;
    my $request    = Dancer::SharedData->request;
    my $serializer = $self->_load_serializer($request);
    return $serializer->serialize($entity);
}

sub deserialize {
    my ($self, $content) = @_;
    my $request    = Dancer::SharedData->request;
    my $serializer = $self->_load_serializer($request);
    return $serializer->deserialize($content);
}

sub content_type {
    my $self = shift;
    $_content_type;
}

sub support_content_type {
    my ($self, $ct) = @_;
    grep /^$ct$/, keys %$serializer;
}

sub _load_serializer {
    my ($self, $request) = @_;

    my $content_types = $self->_find_content_type($request);
    foreach my $ct (@$content_types) {
        if (exists $serializer->{$ct}) {
            my $module = "Dancer::Serializer::" . $serializer->{$ct};
            if (!exists $loaded_serializer->{$module}) {
                if (Dancer::ModuleLoader->load($module)) {
                    my $serializer_object = $module->new;
                    $loaded_serializer->{$module} = $serializer_object;
                }
            }
            $_content_type = $ct;
            return $loaded_serializer->{$module};
        }
    }
}

1;
__END__