1
1

More than 5 years have passed since last update.

MojoliciousでJSON::XSを使う

Last updated at Posted at 2014-04-10

目的

JSON::XSを使って、$c->render(json => ...)を高速化したい。

Mojo::JSON::XSの設定

Mojo::JSON互換のインタフェースを実装したMojo::JSON::XSを使う。

$ cpanm JSON::XS Mojo::JSON::XS

以下のように、render(json => ...)で、このモジュールを使うように置き換える設定をする。

lib/MyApp.pm
use Mojolicious::Lite;
use Mojo::JSON::XS;

...

app->renderer->add_handler(json => sub {
    my ($self, $c, $output, $options) = @_;
    $$output = Mojo::JSON::XS->new->encode($options->{json});
});

...

Mojo::ByteStreamが渡された時の対策

以下のように、
Mojo::ByteStreamのオブジェクトを渡すと、エラーが出てしまう。

myapp.pl
use Mojolicious::Lite;
use Mojo::JSON::XS;
use Mojo::ByteStream 'b';

app->renderer->add_handler(json => sub {
    my ($self, $c, $output, $options) = @_;
    $$output = Mojo::JSON::XS->new->encode($options->{json});
});

get '/' => sub {
    my $self = shift;
    $self->render(json => {name => b('太郎')});
};

app->start;

「encountered object '太郎', but neither allow_blessed, convert_blessed nor allow_tags settings are enabled (or TO_JSON/FREEZE method missing)」

のようなエラーが出る。

通常は、オーバーロードでMojo::ByteStreamのto_stringメソッドが呼び出されるが、
JSON::XSの内部ではblessed判定をしてエラーを出している。

JSON::XSは変換処理をするために、
内部で対象のオブジェクトに対してTO_JSONメソッドを呼び出している。

以下のようにMojo::ByteStreamにTO_JSONメソッドを追加する。

myapp.pl
use Mojolicious::Lite;
use Mojo::JSON::XS;
use Mojo::ByteStream 'b';

app->renderer->add_handler(json => sub {
    my ($self, $c, $output, $options) = @_;
    $$output = Mojo::JSON::XS->new->encode($options->{json});
});

{
    no strict 'refs';
    *{"Mojo::ByteStream::TO_JSON"} = sub {
        my $self = shift;
        $self->to_string; # 自身を文字列に変換する
    };
}

get '/' => sub {
    my $self = shift;
    $self->render(json => {name => b('太郎')});
};

app->start;

これで無事にエラーが出なくなる。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1