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-schemacore.html
JSONの例
{
“id”: 12345,
“name”: “Hiraku NAKANO”,
“tags”: [“PHP”,”JavaScript”]
}
JSON Schema
{

integer

“id”: 12345,
“name”: “Hiraku NAKANO”,
“tags”: [“PHP”,”JavaScript”]
}
id, name, tags という
プロパティを持った
オブジェクト

{

string

string[]

“type”:”object”,
“properties”: {
“id”: {“type”:”integer”},
“name”: {“type”:”string”},
“tags”: {
“type”:”array”,
“items”:{“type”:”string”}
}}}
もし型が違ったら、判定できる
{

integer

“id”: 12345,
“name”: “Hiraku NAKANO”,
“tags”: “PHP,JavaScript”
}
id, name, tags という
プロパティを持った
オブジェクト

{

string

string[]

“type”:”object”,
“properties”: {
“id”: {“type”:”integer”},
“name”: {“type”:”string”},
“tags”: {
“type”:”array”,
“items”:{“type”:”string”}
}}}
バリデーター実装

バリデーション仕様書
• JSONで記述する

• 仕様書を読み取って
バリデーションを実行する
• 言語ごとに存在
• PHP,JavaScript,Ruby,...

JSON
Schema
PHPでの実装
• JSON Schema for PHP がオススメ
https://github.com/justinrainbow/json-schema
• composerの内部で使われている
<?php
require ‘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

スキーマ

{}

{“type”:”object”}

“abc”

{“type”:”string”}

123

{“type”:”integer”}

[1,2,3]

{“type”:”array”}
数値なら上限下限指定できる
JSON

スキーマ

3

{

“type”:”integer”,
“minimum”:2,
“maximum”:5
}
文字列なら正規表現が使える
JSON

スキーマ

“abcdef”

{

“type”:”string”,
“pattern”:”^a.*f$”
}
よく使うパターンはformatで
JSON

スキーマ

“hiraku@tojiru.net”

{

“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

{

スキーマ

{

“type”:”object”,
“properties”:{
“alice”: ...
“bob”: {
“type”:”object”
}
}

“alice”: 123,
“bob”: {
“charlie”: 223
}
}
}

無限に入れ子可能
未定義のプロパティ拒否
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 を多段に入れ子にした構造
例1

$_GET
?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をバリデーションす
ると結構面倒くさい
<?php
if (
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) {
//...
}
<?php
function 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
(依存パッケージもないので割と使いやすいと思う)

完

JSON SchemaとPHP