Mojo::JSONは、「Perlのデータ構造」と「JSON文字列」で、相互に変換してくれるモジュールです。
「Perlのデータ構造」から「JSON文字列」に変換する場合はencodeメソッドを使用し、
「JSON文字列」から「Perlのデータ構造」に変換する場合はdecodeメソッドを使用します。
注意が必要なのは、
Mojo::JSONのencode/decodeが、
Encodeのencode/decodeに合わせたような挙動になっていることです。
encodeメソッド
encodeメソッドに渡すデータの中に日本語などの文字列がある場合は、
utf8フラグを付けておく必要があります。
付けなかった場合は、文字化けが起こります。
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フラグが付いていない状態にする必要があります。
付けている場合は、正常に変換されません。
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フラグが付いている必要があります。
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フラグが付いていないことに注意する必要があります。
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フラグに注意する必要があるという話でした。