PerlでJSONを吐き出す方法、いくつかあるんだけど、どうすればよいか毎回忘れるし、プロジェクトによってJSON::XS使ってたりJSON::Syck使ってたりとまちまちだから、自分なりの方法をここにメモしておく。わりとゆるふわっとしてるので間違いあるかも。
JSONとSyckで同じ出力を得る
念頭にあるのは「安全で文字コードの違いなどを意識せずに扱いたい」ということ。JSONとJSON::Syckでは当然だけどデフォルトの挙動がいくらか違うし、出力されるJSON自体も違う場合がある。
1
2
| #JSON
JSON->new->ascii->utf8(0)->encode(\@data);
|
Unicode文字列を”%uXXXX”形式にエンコードしたいから、JSONではascii
オプションをつける。utf8(0)
はデフォルトの挙動なので無くても良い。
1
2
| #JSON::Syck
Encode::encode('JavaScript-UCS', JSON::Syck::Dump(\@data));
|
こちらJSON::SyckではEncode::JavaScript::UCS
を使うことでそれを実現する。
1
| $json =~ s/([<>\/\+])/sprintf("\\u%04x",ord($1))/eg;
|
それだけじゃ「<、>、+」がそのままなので、置換しておく。それぞれこうすると安全なJSON文字列を得ることができる。これさえ覚えておけばプロジェクトによってどちらが使われていても、同じ結果が得られるAPIが書けるはず。
渡す文字列
euc-jpでencodedな文字列でもsjisでencodedな文字列でも(つまりutf8フラグ無し)、decodedな文字列(utf8フラグ有り)でもなんでも渡せる。
返ってくる文字列
"%uXXXX"
形式にエンコードされたutf8文字列が返ってくる。これを普通のutf8文字列(utf8フラグ無し)にしたければ
1
| Encode::decode('JavaScript-UCS', $str);
|
すれば良いし、あとはeuc-jpとかで欲しければ普通に
1
| Encode::encode('euc-jp', Encode::decode_utf8(Encode::decode('JavaScript-UCS', $str)));
|
すれば良いはず。違ったら教えて。
参考