簡単な例として
{"name":"ほげ"}
とUTF-8エンコードされている日本語を含むJSONを返すAPIがあったとして、WebService::Simpleからそれを取得して値を表示しようとしたとき。
#!/usr/bin/env perl use strict; use warnings; use Amon2::Lite; use WebService::Simple; get '/' => sub { my ($c) = @_; my $ws = WebService::Simple->new( base_url => 'http://****.****/****.json', response_parser => 'JSON', ); my $json = $ws->get->parse_response; return $c->render('index.tt', { name => $json->{name}, }); }; __PACKAGE__->to_app(); __DATA__ @@ index.tt <!doctype html> <html> <body>Hello, [% name %]</body> </html>
こうなる。
どうすればコレを避けられるのかが分からなくて迷走した。
どんぞこ日誌(2010-04-06) によると、
もし外部(ネットやファイルなど)からきたJSONデータがUTF-8でエンコードされてるのがわかっているなら、decode_jsonかutf8オプションを有効にしたJSONオブジェクトを使うべきです。
WebService::Simple::Parser::JSONでは
sub new { my $class = shift; my %args = @_; my $json = delete $args{json} || JSON->new; my $self = $class->SUPER::new(%args); $self->{json} = $json; return $self; }
となっていて、普通に使うとJSONのutf8オプションは有効になっていない。ので、呼ぶ側でuse JSON;
して、
my $ws = WebService::Simple->new( base_url => 'http://****.****/****.json', response_parser => { module => 'JSON', args => { json => JSON->new->utf8, } } ); my $json = $ws->get->parse_response;
のようにutf8オプションが有効になっているJSONオブジェクトを明示的に渡すとか、
my $ws = WebService::Simple->new( base_url => 'http://****.****/****.json', response_parser => 'JSON', ); my $json = decode_json($ws->get->content);
のようにdecodeを任せずに自前でやってしまう、とかで対処する
…のかな?