Upload
hiraku-nakano
View
20.009
Download
6
Embed Size (px)
DESCRIPTION
第72回 PHP勉強会@Engine Yard で発表した資料です。
Citation preview
JSON SchemaとPHP第72回 PHP勉強会@東京
自己紹介
•中野拓
• https://twitter.com/Hiraku
• http://blog.tojiru.net/
• PHP歴6年ぐらい• 最近使ってるフレームワークはYafとPhalconです
• WebAPI関係のお仕事
• 最近コード書いてない。。
第一部
JSON
Schema
JSON Schema
• JSONの構造をバリデーションするための仕様
• http://json-schema.org/
• http://json-schema.org/latest/json-schema-core.html
JSONの例
{
“id”: 12345,
“name”: “Hiraku NAKANO”,
“tags”: [“PHP”,”JavaScript”]
}
JSON Schema
{
“id”: 12345,
“name”: “Hiraku NAKANO”,
“tags”: [“PHP”,”JavaScript”]
}
integer
string
string[]
id, name, tags というプロパティを持ったオブジェクト
{“type”:”object”,“properties”: {“id”: {“type”:”integer”},“name”: {“type”:”string”},“tags”: {
“type”:”array”,“items”:{“type”:”string”}
}}}
もし型が違ったら、判定できる
{
“id”: 12345,
“name”: “Hiraku NAKANO”,
“tags”: “PHP,JavaScript”
}
integer
string
string[]
id, name, tags というプロパティを持ったオブジェクト
{“type”:”object”,“properties”: {“id”: {“type”:”integer”},“name”: {“type”:”string”},“tags”: {
“type”:”array”,“items”:{“type”:”string”}
}}}
JSON Schema
バリデーション仕様書
• JSONで記述する
バリデーター実装
• 仕様書を読み取ってバリデーションを実行する
• 言語ごとに存在
• PHP,JavaScript,Ruby,...
PHPでの実装
• JSON Schema for PHP がオススメhttps://github.com/justinrainbow/json-schema
• composerの内部で使われている
<?phprequire ‘vendor/autoload.php’;
$json = ‘{“a”:1, “b”:2}’;$schema = ‘{“type”:”object”,“properties”:{“a”: {“type”:”integer”},“b”: {“type”:”integer”}
}}’;
$v = new JsonSchema¥Validator;$v->check(json_decode($json), json_decode($schema));
var_dump($v->getErrors()); エラーがあれば指摘してくれる
超単純な例
JSON
{}
“abc”
123
[1,2,3]
スキーマ
{“type”:”object”}
{“type”:”string”}
{“type”:”integer”}
{“type”:”array”}
数値なら上限下限指定できる
JSON
3
スキーマ
{
“type”:”integer”,
“minimum”:2,
“maximum”:5
}
文字列なら正規表現が使える
JSON
“abcdef”
スキーマ
{
“type”:”string”,
“pattern”:”^a.*f$”
}
よく使うパターンはformatで
JSON
スキーマ
{
“type”:”string”,
“format”:”email”
}
date, time, date-time,uri, host-name, email,ipv6, ip-address,color, style,
型固定の配列
JSON
[1,2,3]
スキーマ
{
“type”:”array”,
“items”:{
“type”:”integer”
}
}
配列要素数の制約
JSON
[1,2,3]
スキーマ
{
“type”:”array”,
“minItems”:1,
“maxItems”:5
}
入れ子のオブジェクト
JSON
{
“alice”: 123,
“bob”: {
“charlie”: 223
}
}
スキーマ{“type”:”object”,“properties”:{
“alice”: ...“bob”: {“type”:”object”
}}
}
無限に入れ子可能
未定義のプロパティ拒否
JSON
{
“alice”: 123,
“bob”: 223,
“charlie”: 323
}
スキーマ{“type”:”object”,“properties”: {
“alice”: ...“bob”: ...
},“additionalProperties”:
false}
一通りそろってる感じがする
•詳しくはJSON Schema for PHPのテストを参照!
•入れ子など、構造のバリデーションが得意なのがJSON Schemaの特徴
まとめ
• JSON Schemaを使うと、JSONをチェックして、期待通りの構造になっているか調べることができます。
• PHPにもJSON Schemaの実装があります。
第一部完
...
「JSONの構造をバリデーションして何が嬉しいのか?」についてこれから解説します
第二部
PHPとJSON
突然ですが
PHPはJSONで出来ています
...
って思われそうなのでもう少し丁寧に言うと
PHPのデータ構造はJSON互換です
JSONと言えば
• boolean, number, stringなどの基本的な型
• array, object を多段に入れ子にした構造
$_GET例1
?a[]=1&a[]=2&a[]=3&b=hogehoge
$_GET === [‘a’ => [‘1’,’2’,’3’],‘b’ => ‘hogehoge’
]
JSONだよね!
{“type”:”object”,“properties”:{
“a”:{“type”:”array”,“maxItems”:3
},“b”:{“type”:”string”}
}}
<?php//...$v = new JsonSchema¥Validator;$get = json_decode(json_encode($_GET));
$v->check($get, $schema);
var_dump($v->getErrors());
普通に$_GETをバリデーションすると結構面倒くさい
<?phpif (isset($_GET[‘a’], $_GET[‘b’]) &&is_array($_GET[‘a’]) &&count($_GET[‘a’]) <= 3 &&is_string($_GET[‘b’])
) {//...
}
issetの嵐
これだと何が原因で駄目だったのか分か
らない
もっと入れ子になっていると更に厄介
関数の引数
例2
<?php/*** @param int $a* @param string $b* @param array $config*/function hoge($a, $b, array $config) {//...
}
<?phpfunction hoge($a, $b, array $config) {$args = get_defined_vars();$args === [‘a’ => ...,‘b’ => ...,‘config’ => ...
];}
{“type”:”object”,“properties”:{
“a”:{“type”:”integer”},“b”:{“type”:”string”},“config”:{“type”:”object”,...
}}
}
以下省略
つまり
JSON Schemaとは、JSON相当のデータ構造なら何でもバリデーションできる応用範囲の超広いライブラリなのです
まとめ
•PHP=だいたいJSON
•ゆえに、JSON SchemaはPHPのデータ構造ならだいたい何でもバリデーションできる
•手持ちのバリデーションライブラリの1つとして、覚えておくといいと思います
$ composer require justinrainbow/json-schema(依存パッケージもないので割と使いやすいと思う)
完