WebAPI

JSON Schemaを動的に使いたい話

(「こんなふうにAPIつくりたい話」改め)
@tkawa
Sendagaya.rb 2017-12-18

※まだ実装がないので構想(妄想)の話になりますがご了承ください


RubyKaigi 2017

API Development in 2017 onkさん


スキーマ

正直、スキーマの必要性をあまり感じていなかった

特定のフォーマット使えば良い派だったから

でも、HALなどがあまり普及していないところをみると、求められているものはスキーマなのかも


スキーマ

JSON Schema は「JSON の構造を定義できる」だけで、「API として使う JSON」の定義は JSON Schema の上にもう一つレイヤーが必要。

  • JSON Schema / Hyper-Schema
  • API Blueprint
  • OpenAPI (Swagger)
  • RAML

だいたい全て
* markdown とか YAML とかの書き易いツールで API 定義を書いたら
* ドキュメントがめっちょ綺麗に出力されて
* mock サーバも勝手にできて
* ドキュメントの HTML 上からでも request/response を実際に投げてチェックできる


例えば Swagger の場合

https://swagger.io/specification/
サンプル
https://github.com/OAI/OpenAPI-Specification/blob/master/examples/v3.0/petstore-expanded.yaml
https://github.com/OAI/OpenAPI-Specification/blob/master/examples/v3.0/uber.yaml

パス、メソッド、パラメータ(型)、レスポンスの構造など
これがそのままAPIドキュメントになりそうな記述。
良いように思えるが…

だからパス、メソッド、パラメータは動的なんだって。
動的にしないと変化させることができない。

一応、「リソースタイプ」についての記述ととらえられなくもない。
パス定義は余計だが、「特定のリソースタイプは特定のパスに置かれる」という制約だと解釈できなくもない。(再利用を阻害するけど)


スキーマは動的に(実行時に)解釈できなければならない

RESTful Web APIs 12章より

しかし、「リソースの抽象セマンティックタイプ」と「私のデータモデルでのクラスの実装の詳細」を混同する強い誘惑があります。HydraコンテキストやODataメタデータドキュメントやWADLドキュメントは、サーバサイドのAPI開発者を誘惑して、標準の語彙を再利用する代わりに、それらの内部データモデルに基づいた1回限りの語彙を自動的に生成させます。

そして、私が第9章で前述した大きな問題があります。これらのドキュメントはあまり頻繁に変更されないので、クライアントサイドのAPI開発者は、APIのアプリケーションセマンティクスの完全な概要を提供することが可能なサービス記述ドキュメントとしてそれらを扱うという誘惑にかられます。ユーザは、Hydraコンテキストに基づいてクライアントコードを生成する誘惑にかられるでしょう。それはコンテキストが変化すると壊れてしまうクライアントコードです。


JSON Hyper-Schema

今までの使い方が間違い

  • リソースごとの記述にして、それぞれをリンクさせて実行時に解決できるようにする
    • HTMLに対するCSSのように、JSONに対するスキーマ
  • JSON Schemaをフォームとしても使う。リクエスト・レスポンスどちらの構造もカバーできる

フォーマットとの組み合わせ

  • JSON + JHS
    みんなが最初にやる形。でも結局ルールが決まってないのでやりづらい。
  • HAL + JHS
    HALに欠けているフォームがJHSで補える。コレクションの扱いに難。
  • JSON-LD + JHS
    JSON-LDでやりたいならなぜHydra使わないの?という話ではある

Railsでの実装アイデア

  • JSON Schema をビューテンプレート(app/views)にしてJSONを生成する。
  • JSON Schema を assets(app/assets) として asset pipeline にのせる
  • JSON Schema を assets(app/javascripts) として Webpack にのせる

JSON Schemaはリソースごとに用意する必要があるため、どこでunify(&参照解決)するか。


react-jsonschema-form

react-jsonschema-form playground

JSON Schema (+ UI Schema) に対応するHTMLフォームを組み立てる React component

すでにこれだけできてるから、可能なのでは


懸念

JSON Schema が本当にフォームの代わりに使えるのか
readonly, default, required, disabled, example(placeholder) みたいなもののサポート
バリデーションのコンテキストが必要?

JSON Schemaのセマンティックボキャブラリ拡張になるのかも。


HTMLでやればいいじゃん

その通り

…だけど、React Native版ができたりすると夢がある