この記事はPerl Advent Calendar 2018の10日目の記事です。
JSONをdecodeする時、例えば、123
、"123"
は型に厳しい言語であれば、別々に扱いたいものです。
ですが、Perlでぼやっとencodeすると、これらをいっしょくたにしてしまいます。
例えば、次のコードは123
とencodeされることを期待しても、"123"
とencodeします。
これは、123
のperl内部の値のフラグが意図せず、文字列になり*1、encodeされてしまったからです。
use JSON::XS; my $row = { id => 123 }; # ぼやっと hash key として触る my %fg; $fg{$row->{id}} = 1; print encode_json($row); # => { "id":"123" }
これでは、型に厳しい言語と仲良くできませんね..! 型指定無くencodeしできるのは手軽ではありますが、decode側の言語が期待する型通りencodeできれば、異なる言語間で仲良くできそうです *2。
ここでは、PerlのCpanel::JSON::XS::Type を用いて、期待する型を定義し、encodeする方法について紹介します。
Cpanel::JSON::XS::Typeで型指定をしてencodeする例
早速ですが、型指定をしてencodeする例を示します。
次のコードは、{ id => JSON_TYPE_INT }
という型指定をし、値を"123"
という文字列でなく123
という数値にencodeしています。
use Cpanel::JSON::XS; use Cpanel::JSON::XS::Type; # 型指定 my $type = { id => JSON_TYPE_INT }; print encode_json({ id => "123" }, $type); # => { "id":123 }
encode_jsonの第二引数に型を指定しなければ、従来のencodeを行うので取り入れやすいのではないかと思います。
Cpanel::JSON::XS::Typeで型を定義する
JSONで期待される型は、基本型は数値、文字列、真偽値、nullの4種で、また構造を表現するため、配列、ハッシュがあります。
基本型は、それぞれ、JSON_TYPE_INT|JSON_TYPE_FLOAT、JSON_TYPE_STRING, JSON_TYPE_BOOL、JSON_TYPE_NULLという定数で表し、もし基本型がNULLを取りうるのであれば、_OR_NULL というsuffixを付けます。
配列、ハッシュは、[]
,{}
というリテラル表現か、json_type_arrayof
、json_type_hashof
といった関数を用います。
詳細は、ドキュメントを確認ください。
例えば、このようなデータをencodeする例を考えてみます。
# http://dist.schmorp.de/misc/json/short.json my $data = { 'id' => undef, 'params' => ['user1','we were just talking'], 'array' => ['1',11.01,234,-5,1e5,1e7,!!1,!!0], 'method' => 'handleMessage' };
この場合、型は次のように定義できます。見たままの型定義で、特に理解に支障はないと思います。
my $type = { id => JSON_TYPE_INT_OR_NULL, params => json_type_arrayof(JSON_TYPE_STRING), array => json_type_arrayof(JSON_TYPE_INT_OR_NULL), method => JSON_TYPE_STRING, };
この型を指定し、encodeすると次のようになります。
print encode_json($data, $type) # => {"array":[1,11,234,-5,100000,10000000,1,0],"id":null,"params":["user1","we were just talking"],"method":"handleMessage"}
まとめ
宣伝
YAPC::Tokyo 2019 が1/26(土) に開催されますね! 最高に楽しくなると思う!! ので、来て欲しいです!!!!
チケット販売期限が、今週末予定なので、買い逃しなく!!!!!!