トップ 最新 追記

どんぞこ日誌

2003|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|07|08|12|
2007|01|04|08|12|
2008|01|02|03|04|06|07|08|10|11|12|
2009|01|02|04|05|06|07|08|09|11|12|
2010|01|03|04|07|08|10|11|12|
2011|01|02|03|04|05|06|07|08|10|12|
2012|01|02|03|05|06|07|08|09|10|
2013|01|02|07|08|09|
2014|08|09|
2015|08|
2016|06|07|12|
2017|01|03|08|
2018|03|
2022|03|
2023|03|
2024|02|

同人関連(どんぞこ楽屋) | 旧い雑文   


■2010-04-06

* [Perl][メモ] JSONのドキュメントに追加した部分B!

  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を参照してください。

[]

■2010-04-22

* [Perl][メモ] perl-casual #02のライブコーディングで気づいた点B!

 昨日のperl-casual #02でlestrratさんがtwitter apiからデータを取得するプログラムのライブコーディングをされました。その中で、全然本質的じゃないところなのですが、一点気づいたことがあるので補足を。

LWPを使ってTwitter APIを叩き、JSONデータを展開する部分で:

 # $responseはHTTP::Responseのオブジェクト
 decode_json( $response->decoded_content );

というコード。昨日はちゃんと動作していましたが、場合によっては"Wide character in subroutine entry"でcroakします。これは、$response->decoded_contentが返す値がUnicodeだからです。
 ではなぜ昨日は大丈夫だったかというと、Twitter APIが返したJSONデータは文字列が\uでエスケープされていました。つまり、$response->decoded_contentの返値はUnicode文字列ではあるものの実質asciiだけで構成されています。こういう場合はdecode_jsonもcroakしません。ですから、上記の部分は

 decode_json( $response->content ); # 生のutf-8データ

とした方が安全です。decoded_contentが使いたい場合は

 JSON->new->utf8(0)->decode( $response->decoded_content );

などのようにすると良いでしょう。decode_jsonの動作については、私の先日の記事なども。

* [メモ] 『逆引きAcme大全』を忘れていかれた方へB!

 昨日の懇親会の場で『逆引きAcme大全』を買ったのに本を忘れて帰られた方がいらっしゃるようです。心当たりありましたらmakamaka.donzoko at gmail.com あたりまでご連絡くださいませ。

本日のツッコミ(全2件) [ツッコミを入れる]

_ lestrrat [本当のスクリプトは decode_json $response->content なんだけど、そっちなら大丈夫・・・..]

_ makamaka [昨日はお疲れ様でした〜 はい、それで大丈夫です!> decode_json $response->conten..]

[]