はじめに
構造を定義したJSONを安全に扱うSwiftコードを自動生成する の続きです。
今度はWebAPI用のコードをお手軽に生成することを考えてみます。
任意のHTTP Requestをお手軽に実行する優れたLibraryは本当にたくさんあって、どれにするか迷うくらいです。
ただ、通常のサービスや自分で作っているWebAPIの場合はInterfaceが事前に決まっているにもかかわらず、
リクエストパラメータやレスポンスデータを処理する部分は仕様書を睨みながらコードを書き起こす必要があります。
可能ならばこの辺を省力化したり、型安全の恩恵を受けたいと思うところです。
WebAPI Interfaceの自動生成
Qiita API V2 の一部を例にやってみます。
https://qiita.com/api/v2/docs#get-apiv2items の辺りです。
APIの定義
Qiita API の中から以下の4つを取り出して定義してみます。
- GET /api/v2/items
- POST /api/v2/items
- GET /api/v2/items/:id
- PATCH /api/v2/items/:id
定義はこんな感じになります。
api_prefix: QiitaAPI
entity_prefix: Qiita
api:
ListItem:
get: items
params:
page?: Int
per_page?: Int
response: [Item]
GetItem:
get: items/{id}
response: Item
PostItem:
post: items
body:
body: String
coediting: Bool
gist?: Bool
private: Bool
tags: [Tag]
title: String
tweet?: Bool
PatchItem:
patch: items/{id}
body:
body: String
coediting: Bool
private: Bool
tags: [Tag]
title: String
entity:
Tag:
name: String
versions: [String]
Item:
body: String
coediting: Bool
created_at: String
id: String
private?: Bool
tags: [Tag]
title: String
updated_at: String
url: String
user: User
User:
description?: String
facebook_id?: String
followees_count: Int
followers_count: Int
github_login_name?: String
id: String
items_count: Int
linkedin_id?: String
location?: String
name?: String
organization?: String
profile_image_url?: String
twitter_screen_name?: String
website_url?: String
Swiftコードの生成
こんな感じで生成します。
git clone https://github.com/mokemokechicken/ObjectJsonMapperGenerator.git
cd ObjectJsonMapperGenerator
ruby bin/make_ojm.rb -l swift -t api -c qiita_api.yml > qiita_api.swift
今のところ出力結果はこうなります。
https://gist.github.com/mokemokechicken/ec01464d4e48b04ebc15
使ってみる
生成したコードをプロジェクトに追加しておくと、以下の様な感じで使うことができます。
import Foundation
private let config = QiitaAPIConfig(baseURL: NSURL(string: "http://qiita.com/api/v2/")!)
private let apiFactory = QiitaAPIFactory(config: config)
apiFactory.createListItem().setup(perPage: 3).call { res, items in
items?.map { item in
println("\(item.user.id): \(item.title)")
}
return
}
CFRunLoopRun()
実行結果
mikoski01: Composerを使ってCakePHP環境を楽々構築!(Windows)
mutz0623: CentOSのデフォルトのApacheで、デフォルトのRubyでmod_mrubyをビルド
gam0022: Rails4のアプリをHerokuで動かす
さいごに
こういう風にやると、YAMLで書いた定義がAPI仕様書みたいになるのでなかなか便利に使えますね。
YAMLで記述するとaliasが使える(ある部分を&で定義して、*や<<: *で参照できる)のですが、
これは意外と使える!と思っていたりします(Railsみていて最近気がついた)。
まあ、まだまだ課題はありますが、色々なAPIで試しつつ潰していきたいと思います。
ファイルアップロード、ダウンロードのプログレスバーとか。。。まあ、それくらいなら書いても大したことないけど。。
後はこれを使うModelを似たような感じでひな形が作れれば良いんだけどなぁと思っていますが、
Modelはひな形をベースにしてどんどんコードを追加していく感じになるので、
コード生成という観点ではどういうアプローチがいいのか難しいところです。
ある程度Swift版ができたらJava版も作りたいです。
コードジェネレーターを作るのも少しずつ慣れてきました。何事も練習ですね。
それにしてもコードを全部書き直したい病がしばしば発症するなー