LoginSignup
1
1

More than 5 years have passed since last update.

Mojo::JSONの挙動について

Posted at

Mojo::JSONは、「Perlのデータ構造」と「JSON文字列」で、相互に変換してくれるモジュールです。

「Perlのデータ構造」から「JSON文字列」に変換する場合はencodeメソッドを使用し、
「JSON文字列」から「Perlのデータ構造」に変換する場合はdecodeメソッドを使用します。

注意が必要なのは、
Mojo::JSONのencode/decodeが、
Encodeのencode/decodeに合わせたような挙動になっていることです。

encodeメソッド

encodeメソッドに渡すデータの中に日本語などの文字列がある場合は、
utf8フラグを付けておく必要があります。
付けなかった場合は、文字化けが起こります。

sample.pl
use strict;
use warnings;
use Encode;
use Mojo::JSON;

my $parser = Mojo::JSON->new;

my %data = (
    'name' => decode_utf8('太郎') # utf8フラグを付ける
);

my $json = $parser->encode(¥%data);
print $json; # utf8フラグが付いていない状態になっている

コメントに書いたとおり、encodeメソッドで返ってくるJSON文字列はutf8フラグがついていません。

Mojo::JSON::encodeメソッドでは、

JSON文字列に変換する + utf8フラグを外す

といった処理が行われています。

もし、この処理の後にこのJSON文字列をPerl内で処理する場合は、
再びEncode::decodeでutf8フラグを付ける必要があります。

decodeメソッド

decodeメソッドに渡すJSON文字列は、
utf8フラグが付いていない状態にする必要があります。
付けている場合は、正常に変換されません。

sample.pl
use strict;
use warnings;
use utf8;
use Encode;
use Mojo::JSON;

my $parser = Mojo::JSON->new;

# use utf8; により自動的にutf8フラグがつく
my $json = '{"name": "太郎"}';


my $data = $parser->decode(
    encode_utf8($json) # decodeに渡す場合はutf8フラグを外す
);

# decodeの返り値はutf8フラグがつくので、出力時はutf8フラグを外す
print encode_utf8( $data->{name} );

サンプルではわざとらしく「use utf8」でフラグをつけていますが、
実際には、DBやファイル読み込みで取得したデータに、
utf8フラグが付いていたりするので、
decodeメソッドに渡すときは注意が必要です。

render(json => \%data)

Mojolicious::ControllerのrenderメソッドでJSONを返すときも注意が必要です。
下記に示すように、renderメソッドに渡すデータはutf8フラグが付いている必要があります。

sample.pl
use Mojolicious::Lite;
use utf8;

get '/' => sub {
    my $self = shift;

    # use utf8; により自動的にutf8フラグがつく
    my %data = ('name' => '太郎');

    return $self->render(json => \%data);
}

app->start;

また、partialでJSON文字列を受け取るときは、
その文字列にはutf8フラグが付いていないことに注意する必要があります。

sample.pl
use Mojolicious::Lite;
use utf8;
use Encode;

get '/' => sub {
    my $self = shift;

    my %data = ('name' => '太郎');

    # $json には、utf8フラグが付いていないJSON文字列が入る
    my $json = $self->render(partial => 1, json => \%data);

    # renderで描画する場合は、Encode::decodeを使う
    $self->render(json => decode_utf8($json));
} => 'index';

app->start;

__DATA__

@@ index.html.ep
<% my ($json) = @_; %>
<%= $json %>

Mojo::JSONを使うときは、utf8フラグに注意する必要があるという話でした。

1
1
1

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