JSONスキーマにサーバ側APIについての記述を書けたり、ソースコードが生成できたりするので、いろいろ試してみました。
今回行ったことは次の通りです。
- IIJmioクーポンスイッチAPIのドキュメントを参考に、JSONスキーマを勝手に書いた
- JSONスキーマ用のツールprmdでAPIドキュメントを作成したり、スキーマの検証を行った
- JSONスキーマ用からGo言語のクライアントコードを生成するツールschematicでコードを生成して、それを使った
prmdを導入する
とりあえず、JSONスキーマ用のツールprmdを導入しておきます。gemで一発です。
$ sudo gem install prmd
JSONスキーマを記述する
IIJmioクーポンスイッチAPIを参考に、JSONスキーマを書いてみました。
prmdに雛形を作成する機能があるので、それを利用して書いていきます。
$ mkdir schemata $ prmd init base > schemata/base.json
3つのAPIしかないとは言え、JSONスキーマの仕様について調べながらなので書くのに時間がかかりました。
- Understanding JSON Schema: わかりやすいJSONスキーマの解説
- JSON Schema and Hyper-Schema: JSONスキーマの仕様のドラフトなど
なお、prmdでのスキーマを書く作法的には、メンテナンスしやすいように、APIを機能ごとファイルを分けるように書くとよいみたいです。
基本的には、definitionsあたりにデータやパラメータの定義を書いておき、propertiesにAPIの戻り値オブジェクトの定義を書き、linksにそれが返されるAPIの定義を書く、という感じみたいです。
"$ref": "/foo/bar#/hoge/fuga"みたいなのはJSON Pointerというもので、
この場合は、idが/foo/barなオブジェクトの["hoge"]["fuga"]なオブジェクトを参照するということを意味しています。
ちなみに、既存のサービスとして、Google APIやHeroku Platform APIではAPIにJSONスキーマが用意されているので、それを見て参考にしたりしました。
これらは、例えば次のようにしてJSONスキーマを取得できます (Googleのはブラウザで直接見ることもできます)。
curl https://api.heroku.com/schema -H "Accept: application/vnd.heroku+json; version=3" curl -O https://www.googleapis.com/discovery/v1/apis
prmdでAPIドキュメントを作成する
JSONスキーマを書き終えたら、まずprmdで分割したファイルを結合して、ひとつのスキーマにします。
$ mkdir gen $ prmd combine --meta meta/meta.json schemata > gen/schema.json
なお、meta.jsonは次のようなファイルです。
$ cat meta/meta.json
{
"description": "IIJmio Coupon API",
"id": "iijmio",
"links": [{
"href": "https://api.iijmio.jp/mobile/d/v1",
"rel": "self"
}],
"title": "IIJmio"
}
続いて、作成されたスキーマが正しいか検証してみます。
$ prmd verify gen/schema.json
エラー報告がなければドキュメントを生成してみましょう。
$ prmd doc gen/schema.json > gen/schema.md
これで生成されたドキュメントはこちら。
Attributesのあたりがやたら見づらいですが、それっぽい感じのドキュメントになっています。
schematicでGoのクライアントコードを生成する
最後に、Go言語のJSONスキーマ用ツールschematicでクライアントコードの雛形をつくって、それを利用してみましょう。
まず、schematicをてきとうに導入します。
$ git clone https://github.com/interagent/schematic.git $ cd schematic $ go build cmd/schematic/schematic.go
schematicの使いかたは、schematic foo.json > foo.goでよいのですが、日本語コードが入っているとエラーになるようなので、次のようにてきとうに取り除きました。
$ mkdir -p src/iijmio $ schematic =(sed -E 's/"description":.+//' gen/schema.json) > src/iijmio/iijmio.go
そして、生成されたコードがそのままでは利用できないので、を次のように修正しました。
timeパッケージがなぜかimportされているが、不要なのでコメントアウトしたVersionが空文字なので入れておいたreq.HeaderにX-IIJmio-DeveloperとX-IIJmio-Authorizationを入れておいた- コードでは
Getがトップレベルがリストであるデータ取得を想定しているが、クーポンAPIではそうではないので、リストを取らないようにした
具体的な修正内容はこのコミットを見てください。
あとは、これを利用するメインコードを書いて終わりです。
package main
import (
"iijmio"
"fmt"
)
func main() {
mio := iijmio.NewService(nil)
cs, err := mio.CouponList(nil)
fmt.Println(cs, err)
ps, err := mio.PacketList(nil)
fmt.Println(ps, err)
}
これを実行すると次のような感じで出力されます (実際にはインデントや改行は入りません)。
&{[
{[{0xc208249140 bundle 1420}
{0xc208249160 bundle 2000}
{0xc208249180 topup 0}
{0xc2082491a0 topup 0}
{0xc2082491c0 topup 0}
{0xc2082491e0 topup 0}]
hddzzzzzzzz
[{[{<nil> sim 1}] true
hdoxxxxxxxx GDxxxxxxxxxxxx yyyyyyyyyyy
false false false}] Minimum Start}
{[{0xc208249330 bundle 120}
{0xc208249350 bundle 2000}
{0xc208249370 topup 0}
{0xc2082493a0 topup 0}
{0xc2082493c0 topup 0}
{0xc2082493e0 topup 0}]
hddxxxxxxxy
[{[{<nil> sim 6}] true
hdoxxxxxxxy DNxxxxxxxxxxxxy yyyyyyyyyyz
false true true}] Minimum Start}]
OK} <nil>
&{[
{hddxxxxxxxx
[{hdoxxxxxxxx
[{20141006 33 0}
{20141007 64 0}
{20141008 60 15}
:
]}] Minimum Start}
{hddxxxxxxxy
[{hdoxxxxxxxxy
[{20141006 0 0}
{20141007 0 0}
{20141008 0 0}
]}] Minimum Start}
] OK} <nil>
ちなみに、クーポン利用状態変更については、できるかどうか確認していません。というか、メソッドCouponChangeを呼ぶためのコードが私には書けませんでした。
func (s *Service) CouponChange(o struct {
CouponInfo []struct {
HdoInfo []struct {
CouponUse bool `json:"couponUse"`
HdoServiceCode string `json:"hdoServiceCode"`
} `json:"hdoInfo"`
} `json:"couponInfo"`
}) (*Coupon, error) {
var coupon Coupon
return &coupon, s.Put(&coupon, fmt.Sprintf("/coupon/"), o)
}
おわりに
JSONスキーマをつくって、そこからGo言語コードを自動生成してみました。
JSONオブジェクトを定義するだけではなく、REST APIをより詳しく定義したい場合にはSwaggerというものもあるみたいです。swaggerの仕様にはREST API向けの属性がいろいろ定義されているので便利そうです。
また、今回はJSONスキーマを手書きで書きましたが、ソースコードから自動生成するというアプローチもあるみたいです。例えば、Go言語のbeego Webフレームワークを利用していたら、コードのコメントからSwaggerのスペックファイルを生成したりできるようです。
関連リンク
- Safx: MacでGoのデバッグ環境を構築する
- Safx: Go言語のBDDテストツールGoConveyを使ってみる
- IIJmioクーポンスイッチAPI
- interagent/prmd · GitHub
- interagent/schematic · GitHub
- Schemataのドキュメント
- Understanding JSON Schema — Understanding JSON Schema 1.0 documentation
- JSON Schema and Hyper-Schema
- draft-ietf-appsawg-json-pointer–07 - JavaScript Object Notation (JSON) Pointer
- Swagger: A simple, open standard for describing REST APIs with JSON | Reverb for Developers
- Getting Started - Google APIs Discovery Service — Google Developers

0 件のコメント:
コメントを投稿
注: コメントを投稿できるのは、このブログのメンバーだけです。