Canonical な JSON エンコーディング
あるデータ表現を JSON にエンコーディングする際、常に同じキーの順番でエンコーディングして欲しいことがあります。 例えば JSON Web Token (参考) は JSON 文字列をトークンとして用いるので(正確には更に Base64 エンコーディングしたもの)、 中身は同じ内容でも JSON へのエンコーディングの仕方によっては最終的なトークン文字列が異なるものになってしまいます。 特に Perl の場合は Perl v5.18 からハッシュのランダム化 がされるので、 JSON エンコーディングする度に異なる文字列が得られる可能性が高いです。
Canonical JSON
常に同じキーの順番でエンコーディングされる JSON のことを Canonical (正準) JSON と言ったりするそうです。
Perl では JSON.pm の canonical
メソッドで Canonical モードにすることが出来ます。
use JSON; my $json = JSON->new->canonical;
Example
#!/usr/bin/env perl use strict; use warnings; use v5.18; use JSON; for (1..3) { my $hash = +{ foo => 1, bar => 2, baz => 3 }; say JSON->new->encode($hash); } say ''; for (1..3) { my $hash = +{ foo => 1, bar => 2, baz => 3 }; say JSON->new->canonical->encode($hash); }
結果
{"bar":2,"baz":3,"foo":1} {"foo":1,"baz":3,"bar":2} {"baz":3,"bar":2,"foo":1} {"bar":2,"baz":3,"foo":1} {"bar":2,"baz":3,"foo":1} {"bar":2,"baz":3,"foo":1}
Canonical な JSON は常にキーでソートされた順番でエンコーディングされていることがわかると思います。 JSON Web Token など常に同じ JSON 文字列を期待する場面では Canonical JSON を使用しましょう。