今日はJSON.pmの小ネタをお送りします. ...といっても割と既知な情報では? という気がしているのですが, 自分は知らなくて10分くらいJSON.pmのドキュメント読んだりしてやっと見つけたので, 備忘録的に残しておきます.
さて, JSON.pmを使って, 普通にPerlのハッシュによるデータ構造をJSONに変換しようとすると, 生成されたJSONのキーの順序は生成する度に異なる順序になってしまいます.
use strict; use warnings; use JSON qw/ encode_json /; my $json = encode_json({ a => 1, b => 2, c => 3 }); print "$json\n";
例えば, このコードをPerl 5.20で実行すると...
$ perl json.pl {"c":3,"a":1,"b":2} $ perl json.pl {"a":1,"c":3,"b":2} $ perl json.pl {"b":2,"c":3,"a":1}
こんな感じで, 毎回キーの順番が異なってしまいます(例えば, 1回目はc
, a
, b
の順番ですが, 2回目はa
, c
, b
になっていますよね).
APIを実装していて, ユーザに対してJSONを返す場合であれば, これでも特に問題はありません. しかし, 何かしらのマスターデータからJSON形式のデータを生成してファイルに保存する... という場合, 生成後のJSONのキーの順番が毎回バラバラだと, 例えばJSONが書き込まれたファイルをGitで管理している場合, (JSONのキーの順序がJSONを生成する度に変化するので)毎回不要な差分が生じてしまい, 不便です.
こういう時は, JSON.pmのCanonicalモードを使えばいいそうです.
use strict; use warnings; use JSON; my $json = JSON->new->utf8->canonical->encode({ a => 1, b => 2, c => 3 }); print "$json\n";
こういう感じにしてやると...
$ perl json.pl {"a":1,"b":2,"c":3} $ perl json.pl {"a":1,"b":2,"c":3} $ perl json.pl {"a":1,"b":2,"c":3}
何度JSONを生成しても, 毎回同じキーの順序になっていることがわかります!
余談
ちなみに, canonical
だけでなくutf8
も通しているのは, canonical
を有効にしながら, encode_json
と同じようにJSONを生成したいからです.
要するに, JSON.pmを普通に使う場合の,
use strict; use warnings; use JSON qw/ encode_json /; my $json = encode_json({ a => 1, b => 2, c => 3 }); print "$json\n";
というコードは,
use strict; use warnings; use JSON; my $json = JSON->new->utf8->encode({ a => 1, b => 2, c => 3 }); print "$json\n";
と同じ事をしている, というわけです.
以上, PerlのJSON.pmについての小ネタでした.