Slide 1

Slide 1 text

PerlとJSON id:papix (@__papix__) 株式会社はてな

Slide 2

Slide 2 text

papix 株式会社はてな アプリケーションエンジニア (2017年2月~) シニアエンジニア (2019年2月~) ブログMediaチーム サービスリード兼スクラムマスター 「はてなブログ」をつくっています アカウント類 はてな: id:papix Twitter: @__papix__ GitHub: papix / CPAN: PAPIX ブログ: https://papix.hatena(blog.(com|jp)|diary.jp)/ 趣味はPerlと, (交通機関を利用した)旅行 JGC修行は完遂済み, 今年はSFC修行をしています

Slide 3

Slide 3 text

JSON JavaScript Object Notation JavaScript Object Notation (JSON 、ジェイソン)は軽量な データ記述言語の1 つである。構文はJavaScript におけるオブジ ェクトの表記法をベースとしているが、JSON はJavaScript 専用の データ形式では決してなく、様々なソフトウェアやプログラミング 言語間におけるデータの受け渡しに使えるよう設計されている。 by Wikipedia Perlでも, JSONを扱うライブラリが用意されている

Slide 4

Slide 4 text

Perl界の(代表的な)3つのJSON JSON::PP JSON::XS JSON

Slide 5

Slide 5 text

JSON::PP PP(Pure Perl)実装のJSONモジュール v5.13.9よりコアモジュール perl コマンド単体で動かしたいスクリプトならJSON::PPを 使っておくと良い

Slide 6

Slide 6 text

JSON::XS XSを使ったJSONの実装 XSを使って, C言語のコードやライブラリとPerlを繋いで実装 しているので(Pure Perlよりも)高速 cpanfile などに書いていて, JSON::XSがある環境なら明示的に JSON::XSを使えばよい コアモジュールではない

Slide 7

Slide 7 text

JSON JSON::XSがあればそれを, なければJSON::PPを使ってくれる モジュールなどで, よしなに使わけて欲しい時はJSONを使って おけばよい コアモジュールではない

Slide 8

Slide 8 text

まだまだあるJSONファミリー Cpanel::JSON::XS Cpanelという会社が実装した, XSを使ったJSON JSON::MaybeXS Cpanel::JSON::XSとJSON::XSとJSON::PPをよしなに使って くれる

Slide 9

Slide 9 text

JSONことはじめ JSON::XSを例に, Perlで実際にJSONを扱う例を紹介していきます

Slide 10

Slide 10 text

PerlのHash/ArrayリファレンスをJSONにする use JSON::XS qw(encode_json); my $json = encode_json({ a => 1, b => 2 }); print $json; # => {"a":1,"b":2}

Slide 11

Slide 11 text

JSONをPerlのデータ構造にする use JSON::XS qw(decode_json); use Data::Dumper; my $ref = decode_json('{"a":1,"b":2}'); print Dumper $ref; # $VAR1 = { # 'a' => 1, # 'b' => 2 # };

Slide 12

Slide 12 text

ちなみに... decode_json は, JSON::XS->new->utf8->decode と同じ encode_json は, JSON::XS->new->utf8->encode と同じ use JSON::XS; my $json = JSON::XS->new->utf8->encode( { a => 1, b => 2, c => 3 } );

Slide 13

Slide 13 text

こういう時はどうする?

Slide 14

Slide 14 text

JSONにする時, Hash Randomizationを回避したい Perl 5.18以降, Hash Randomizationが導入された PerlのHash/ArrayリファレンスをJSONにするとき, キーの順序 が不順になることがある use JSON::XS qw(encode_json); my $json = encode_json({ a => 1, b => 2, c => 3 }); print "$json\n"; $ 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}

Slide 15

Slide 15 text

JSONにする時, Hash Randomizationを回避したい 解決策としては, Canonicalモードを使う キーをソートした上でJSONにしてくれる use JSON::XS; my $json = JSON::XS->new->utf8->canonical->encode( { a => 1, b => 2, c => 3 } ); print "$json\n"; # {"a":1,"b":2,"c":3}

Slide 16

Slide 16 text

JSONにするとき, オブジェクトが含まれていても無視したい PerlのHash/ArrayリファレンスをJSONにするとき, 通常オブジェク トが含まれると例外になる encountered object 'Obj=HASH(0x7ff069003418)', but neither allow_blessed, convert_blessed nor allow_tags settings are enabled (or TO_JSON/FREEZE method missing) use JSON::XS qw(encode_json); my $hash = { a => 1, b => Obj->new, }; my $json = encode_json($hash); # XXX

Slide 17

Slide 17 text

JSONにするとき, オブジェクトが含まれていても無視したい allow_blessed をOnにすると, オブジェクトは無視して null に してくれる use JSON::XS qw(encode_json); my $hash = { a => 1, b => Obj->new, }; my $json = JSON::XS->new->utf8->allow_blessed->encode( $hash ); print $json; # => {"a":1,"b":null}

Slide 18

Slide 18 text

JSONにするとき, オブジェクトもよしなにJSONにしたい オブジェクト側に TO_JSON メソッドを用意しておけば, オブジェク トの TO_JSON の返り値でJSONを作ってくれる use JSON::XS; my $hash = { a => 'b', c => Obj->new, }; my $json = encode_json($hash); print $json; # => {"a":"b","c":{"cc":11}} package Obj; sub new { bless {}, $_[0] } sub TO_JSON { {cc => 11} }

Slide 19

Slide 19 text

JSONにするとき, 型を明示したい JSON::Typesを使いましょう use JSON::XS; use JSON::Types; my $hash = { number => JSON::Types::number 1, string => JSON::Types::string 1, bool => JSON::Types::bool 1, }; my $json = encode_json($hash); print $json; # {"number":1,"string":"1","bool":true}

Slide 20

Slide 20 text

JSON::Types 実装は素朴 sub number($) { return undef unless defined $_[0]; $_[0] + 0; } sub string($) { return undef unless defined $_[0]; $_[0] . ''; } sub bool($) { $_[0] ? \1 : \0; }

Slide 21

Slide 21 text

ちなみに... booleanについては, (Perlに存在しない概念なので)decodeするとき にどうなるかはライブラリごとに決まっている 例えば, JSON::XSなら, true は $Types::Serialiser::true に, false は $Types::Serialiser::false にデコードされる 更に, boolean_values を使って, JSONの true / false をデ コードするときの値を上書きすることができる

Slide 22

Slide 22 text

まとめ PerlにはJSONを扱うための道具がいろいろある そしてJSONをよしなに扱うテクニックがいろいろある PerlとJSONとうまくつきあっていきましょう