■2010-04-06
* [Perl][メモ] JSONのドキュメントに追加した部分
tokuhiromさんに(en|de)code_json
と(to|from)_json
どっちを使ったほうが良いのか初心者にわかるようにしたらと言われたので、最近のJSON.pmのドキュメントには(en|de)code_json
がオススメである旨が付け足されています。さらに念を押して、一応自分ではわかりやすく説明したつもりの"HOW DO I DECODE A DATA FROM OUTER AND ENCODE TO OUTER"というセクションが加わっています。
で、この日誌にperl json 文字化けとかで検索してくる人がたまにいて、たぶんこのページがヒットするのでしょうが、(自分で訳しておいて何ですが)これ見てもわかりにくいんじゃないかなあという気がします。また、先のgoogleの検索結果のトップには現状Kawa.netさんの2008年初頭のページが最初の方に表示されますが、UTF8フラグ云々の話が書いてあって初心者向けじゃないと思うので、何かの参考になるかもしれないので"HOW DO I DECODE A DATA FROM OUTER AND ENCODE TO OUTER"の和訳を掲載しておきます。
※PerlとUNICODEについてはこの辺りでperluniから始まるファイルを読んでみてください。
どのように外部からのデータをdecodeするか、外部へとencodeするか
このセクションはPerl5.8以降を想定しています。
もし外部(ネットやファイルなど)からきたJSONデータがUTF-8でエンコードされてるのがわかっているなら、decode_json
かutf8オプションを有効にしたJSONオブジェクトを使うべきです。decodeされた結果はUNICODEキャラクタを含んでいるでしょう。
# ネットから my $json = JSON->new->utf8; my $json_text = CGI->new->param( 'json_data' ); my $perl_scalar = $json->decode( $json_text ); # ファイルから local $/; open( my $fh, '<', 'json.data' ); $json_text = <$fh>; $perl_scalar = decode_json( $json_text );
もし外部データがUTF-8でないなら、まずはそのデータをdecode
します。
use Encode; local $/; open( my $fh, '<', 'json.data' ); my $encoding = 'cp932'; my $unicode_json_text = decode( $encoding, <$fh> ); # あるいは下のように # # open( my $fh, "<:encoding($encoding)", 'json.data' ); # $unicode_json_text = <$fh>;
この場合、$unicode_json_text
はもちろんUNICODEな文字列です。ですから、decode_json
やutf8オプションを有効にしたJSONオブジェクトは使えません。代わりに、utf8オプションを無効にしたJSONオブジェクトか、from_json
を使います。
$perl_scalar = $json->utf8(0)->decode( $unicode_json_text ); # または $perl_scalar = from_json( $unicode_json_text );
あるいはencode 'utf8'
してからdecode_json
します。
$perl_scalar = decode_json( encode( 'utf8', $unicode_json_text ) ); # 効率的ではない
今度は、$perl_scalar
をJSONデータに変換して外部(ネットやファイルなど)へと送ります。
通常あなたのデータはUNICODE文字列を含んでいます。UTF-8でエンコードされたJSONデータにするなら、encode_json
かutf8オプションを有効にしたJSONオブジェクトを使うべきです。
print encode_json( $perl_scalar ); # または print $json->utf8->encode( $perl_scalar );
何らかの理由で$perl_scalar
がUNICODEではなく$encoding
でエンコードされた文字列を含んでいる場合、そのキャラクタはlatin1
とみなされます(perlはあなたの$encoding
を気にしません)。encode_json
やutf8オプションを有効にしたJSONオブジェクトは使えません。代わりにutf8オプションを無効にしたJSONオブジェクトか、to_json
を使います。この結果生成されるテキストはUNICODEですが、出力しても問題ありません。
# $perl_scalarは$encodingでエンコードされた値を持つ $unicode_json_text = $json->utf8(0)->encode( $perl_scalar ); # または $unicode_json_text = to_json( $perl_scalar ); # $unicode_json_textは0x100未満のキャラクタで構成されている print $unicode_json_text;
あるいは文字列を全部deocde $encoding
してからencode_json
する:
$perl_scalar->{ foo } = decode( $encoding, $perl_scalar->{ foo } ); # 全部の内容にたいして上記操作を…… $json_text = encode_json( $perl_scalar );
この方法は適切ではありますが、たぶん効率悪いです。
Encodeやperluniintroを参照してください。