Rails での JSON API 実装まとめ
前後リンク
- RESTful API のおさらい
- Rails での JSON API 実装まとめ
- スキーマファースト開発
- The NEXT of REST
Ruby on JSON
の図のような流れになるんですが、それぞれ見ていきます。
to_json (2011-2013 頃)
2011-2013 年頃、僕らはrender :json を使っていました。
render json: @userrender json: @user.to_jsonとしてUser#as_json やUser#to_json を利用します。
この頃はまだ SPA という言葉もなく、ネイティブアプリもそこまで流行っていなかったのでこれで十分だったのですが、どんどん API に世の中が寄っていき、限界を迎えます。
この頃のツラみ
- JSON を組み立てるのが大変

- 何が返るのか分からない

- 「リソース」の存在を強制できていない

- テストが大変

JSON Template engines (2013-2015 頃)
JSON を組み立てる方法として、RABL や jbuilder といったJSON 用のテンプレートエンジンを使う方法が出てきます。
RABL: 2011年からある老舗の gem。独特の言語で記述する必要があるので学習コストが高め。
jbuilder: rails4 から標準になった。割と簡単に柔軟に書ける。
どちらも「JSON は view」という考え方で、controller では普通に model を assign して、view で JSON を render する。
この頃のツラみと解決
- JSON を組み立てるのが大変
- JSON を組み立てる用の DSL によって解決した!

- JSON を組み立てる用の DSL によって解決した!
- 何が返るのか分からない
- 変わらず大変だけど、view を見れば分かるので少し分かりやすくなった

- ghost_writer やautodoc でドキュメントを自動生成するようになる
- 変わらず大変だけど、view を見れば分かるので少し分かりやすくなった
- 「リソース」の存在を強制できていない
- 部分テンプレートに分割することでリソースを表現可能に

- だが jbuilder の部分テンプレートは異常に遅いのだった……!!

- 部分テンプレートに分割することでリソースを表現可能に
- テストが大変
- 変わらず大変

- rspec-json_matcher やstrong_json で頑張る
- 変わらず大変
ActiveModelSerializers (2014-)
jbuilder は部分テンプレートのレンダリングが異常に遅く、例えばユーザデータ 200 件を含む JSON を返したいだけで 50ms 以上食われることがザラにあった。
このため、遅いところでは「インラインに展開する」とか「to_json を使う」とかを頻繁に行っていて、これを解決するために serializer 層が生まれた。
AMoS はその流れで出てきたライブラリで、
- app/serializers 以下に置くので HTML と混ざらない
- 単体でテストが書ける
という serializer としてのメリットと、
- HogeSerializer を定義するだけで使える簡便性
- DSL チックじゃないので書きやすくて読み易い
という利点、あと何より速さで使われ出した。
render json: @userclass UserSerializer < ActiveModel::Serializer attributes :id, :name, :birthday def birthday object.created_at.strftime("%Y/%m/%d") endendこの頃のツラみと解決
- JSON を組み立てるのが大変
- 更に簡単になった!

- 更に簡単になった!
- 何が返るのか分からない
- かなり読みやすいので、「サーバの実装が正」が許される状況ならautodoc 等のドキュメンテーションツールがなくても「実装読んでね」が使えるかも?

- かなり読みやすいので、「サーバの実装が正」が許される状況ならautodoc 等のドキュメンテーションツールがなくても「実装読んでね」が使えるかも?
- 「リソース」の存在を強制できていない
- Serializer がリソースになるので解決

- Serializer がリソースになるので解決
- テストが大変
- 相変わらず面倒です……。

- 相変わらず面倒です……。
- jbuilder の異常に遅い partial rendering
- 普通の速度で返せるようになった

- 普通の速度で返せるようになった
Grape (2012-2014 頃)
この流れとは別に、Grape が存在しました。REST API を作成するためのマイクロフレームワークです。
class UserEntity < Grape::Entity expose :id expose :name expose :birthdayendclass API < Grape::API format :json resources :users do get ":id" do present User.find(params.id), with: UserEntity end endendgrape の記法を学ばなければならず、学習コストは高い。DSL だけあって、API 定義 (Entity) と router は割と読みやすいので慣れれば楽かも。
この頃のツラみと解決
- JSON を組み立てるのが大変
- 簡単になった!

- 簡単になった!
- 何が返るのか分からない
- かなり読みやすいので、「サーバの実装が正」が許される状況ならautodoc 等のドキュメンテーションツールがなくても「実装読んでね」が使えるかも?

- かなり読みやすいので、「サーバの実装が正」が許される状況ならautodoc 等のドキュメンテーションツールがなくても「実装読んでね」が使えるかも?
- 「リソース」の存在を強制できていない
- Entity がリソースです

- Entity がリソースです
- テストが大変
- 相変わらず面倒です……。

- 相変わらず面倒です……。
AMoS と同じように問題を解決しているんだけど、いかんせん独自フレームワーク、独自 DSL だったのがネックですね。Rails じゃないと使われないという悲しみがあるのでした。
JSON Schema (2014-2016 頃)
JSON Schema とは: JSON で表現されるデータに対してデータ定義する Schema を記述する仕組み。
超簡単な例だと以下のようなデータと schema 定義。(概念コードです
{ "id": 12345678, "name": "Taro", "birthday": "2000-01-01 00:00:00"}properties: id: type: integer name: type: string birthday: type: date-timeこの頃のツラみと解決
- JSON を組み立てるのが大変
- JSON Schema は直行する概念なのでどんな JSON 生成技術とも一緒に使えます

- JSON Schema は直行する概念なのでどんな JSON 生成技術とも一緒に使えます
- 何が返るのか分からない
- 返す JSON のスキーマを書いていくので、まさに「何を返すか」が分かります

- スキーマがあるので、HTML ドキュメントも自動生成することができます。
- 返す JSON のスキーマを書いていくので、まさに「何を返すか」が分かります
- 「リソース」の存在を強制できていない
- これも JSON 生成処理次第

- これも JSON 生成処理次第
- テストが大変
- ここが解決します!

- スキーマをデータの検証に使うことができます
- 入力値や、返した値が仕様を満たしているかどうかのテストを書けるようになった
- すべての request/response を機械的にチェックすることで仕様と実装の乖離が生まれない状況が作れる
- ここが解決します!
また、他に
- JSON/YAML なので Ruby が分からなくても書ける

- サーバ担当が書くまで決まらないという流れからの脱却。インタフェースを決めた段階で、誰でもスキーマを記述することができます。
- API Client が作れる

- サーバがどんなリクエストを要求しているかのスキーマがあるので、リクエストを投げる側のメソッドを自動生成することができます
といった辺りも大きなメリットです。
先駆者たち
DeNA、Cookpad 等。2014年の中頃辺りから盛り上がってきた。
- JSON Schema と API テスト YAPC::Asia Tokyo 2014
- 全てがJSONになる - ✘╹◡╹✘
- Qiita API v2のJSON Schemaを公開しました - Qiita Blog
API Description Language (2016-)
JSON Schema は基盤となり、JSON Schema の上で API を記述する言語が生まれてきます。
JSON Schema は「JSON の構造を定義できる」だけで、API として使う JSON」の定義はJSON Schema の上にもう一つレイヤーが必要。
そこで出てきたのが以下の諸々で、現在 5 派閥ぐらいありそうです。
- API Blueprint
- apiary で使われているスキーマ定義
- OpenAPI
- 最大派閥っぽい
- Swagger で使われているスキーマ定義
- RAML
- チャットワークAPIドキュメント で使われています
- JSON Hyper-Schema
- 生 JSON Schema
だいたい全て
- markdown とか YAML とかの書き易いツールで API 定義を書いたら
- ドキュメントがめっちょ綺麗に出力されて
- mock サーバも勝手にできて
- ドキュメントの HTML 上からでも request/response を実際に投げてチェックできる
みたいな機能を備えてます。
この頃のツラみと解決
- JSON を組み立てるのが大変
- どんな JSON 生成技術とも一緒に使えます

- どんな JSON 生成技術とも一緒に使えます
- 何が返るのか分からない
- 更に読みやすくなりました!

- 更に読みやすくなりました!
- 「リソース」の存在を強制できていない
- リソースを記述できるようになりました!

- リソースを記述できるようになりました!
- テストが大変
- こちらも引き続き改善されています

- こちらも引き続き改善されています
当時ツラかった内容が全て解決していますね。
参考URL
- API Blueprintとその周辺ツール - Qiita
- 僕が考えた最強のAPIドキュメント生成 - 銀の人のメモ帳
- GoConの前哨戦として各種API仕様記述フォーマットについて概要を述べておく - Qiita
API Query Language (2016-)
GraphQL が爆誕します。
GraphQL は今までの流れでも解決できていない、「そもそも REST は本質的に難しくて徹底できない。RESTish が限界」ということを認めて、別のアプローチを取ります。
もちろんデメリットもあります。
詳しくは第 4 部The NEXT of REST で。
前後リンク
- RESTful API のおさらい
- Rails での JSON API 実装まとめ
- スキーマファースト開発
- The NEXT of REST
