前の記事([Sinatra] シンプルな JSON API サーバーに手を加える(RSpec でテスト))に続いて、JSON Schema でデータのバリデーションをしてみる
おしながき
- POST でデータを登録できるようにする
- RSpec でテストする
- データを JSON Schema でバリデーションする
JSON Schema とは
JSON Schema とは、ある JSON が正しい構造・仕様を満たしているかを検証する仕組みで、JSON Schema 自体が JSON で記述される。
とりあえず最低限のスキーマとそれを満たす JSON を見てみる
例 1
Schema
{ |
対象の JSON
{ |
まず一番外側にオブジェクト("type": "object"
)があり、数値("type": "integer"
)の値を持つ "hoge"
をプロパティとして持つ、と読める。
なので以下のような JSON は数値が入るべきところを文字が入っているのでバリデーションで弾かれる。
{ |
例 2
一番外側はオブジェクトじゃなくてもいい、配列("type": "array"
)の場合はこうだ
Schema
{ |
対象の JSON
[1, 2, 3] |
たったこれだけの内容でも、愚直にコードでバリデーションを掛けるとわりと大変だ(ハッシュを再帰的に走査してプロパティを一個ずつチェックするとか…?)そこでターゲットの JSON に対し定義済みのスキーマを被せてバリデーションするイメージの JSON Schema は簡単で分かりやすい。
上記は本当に最低限動くサンプルでしかないので、もう少し実用的な記法は以下を参照
JSON Schema の書き方については一応本稿の趣旨ではないので…外部に丸投げする
また、バリデーションのチェックは JSON Schema Validator のような Web のツールを使うと楽だ
Ruby でやるには
ruby-json-schema/json-schema という gem を使う。この gem では JSON Schema Draft 4 を使用しているので、以後 Draft 4 に準ずる形で進める。
ちなみに登録するデータは
{ |
で、利用するスキーマは
{ |
になる。
単純に弾くだけ
単にエラーを弾くだけなら post メソッドへは一行追加するだけでいい(スキーマは書かなきゃだけど…)
SCHEMA = { |
これでバリデーションに失敗した場合 500 エラーになる。
メッセージも通知する
単純に弾くだけだと何で弾かれたかわからないので、500 にメッセージを乗せてあげる
JSON::Validator.validate
ではなく JSON::Validator.fully_validate
を使う。fully_validate を使うと、true/false ではなく 空配列/エラーメッセージ入り配列 で結果を返すようになる。
SCHEMA = { |
これで具体的にどこが弾かれたか通知されるようになった。
さいごに
Sinatra において、POST の Body(JSON)のバリデーションを JSON Schema で行うことができた。
今回は Sinatra にベタ書いているけど、例えば GET で返す JSON をモデルから自動生成したり
(r7kamura/json_world)、Rack レベルでバリデーションを掛けたり(r7kamura/rack-json_schema)もできるらしい。
そもそもボクが JSON Schema を知ったきっかけが全てが JSON になる - ✘╹◡╹✘というブログで、上記のライブラリもこの作者さんのものなんだが、このライブラリ群を見てるとマジで「全てが JSON になる」と思えるようになる。マジですごい(小並感)
実行環境
- Ruby 2.3.3
- Sinatra 2.0.3
- json-schema 2.8.0