はじめに
vimeoのAPIライブラリを実装したときに便利だったgo-jsonの紹介と問題点、その改良について書きます。
使いどころ
以下の条件が揃ったとき、go-jsonのありがたみが感じられます。
- APIクライアントを実装する必要がある
- レスポンスのタイプがJSONである
- APIのレスポンス内容が多い
- レスポンスのサンプル値が簡単に手に入る
使い方
まずは通常通りインストール
$ go get github.com/ChimeraCoder/gojson/gojson
ドキュメント等からJSONのレスポンス値を集め
$ ls *.json
group.json list.json me.json video.json
go-jsonで構造体を一括生成します
-pkg
はpackage名、-name
は構造体名、-input
変換元のJSONファイル、-o
で出力先です
for f in $(ls); do
name=$(echo $f|sed 's/.json//g')
gojson -subStruct true -pkg vimeo -name ${name^} -input $f -o ${name}.go
done
また、生成時に-subStruct
オプションをtrue
にしているので
ネストしているJSONは、Size struct{...}
ではなく別の構造体に分割されます
{
"id": "2321232",
"created_at": "2016/12/24",
"size": {
"width": 400,
"height": 860
}
}
package vimeo
type Video struct {
CreatedAt string `json:"created_at"`
ID string `json:"id"`
Size Video_sub1 `json:"size"`
}
type Video_sub1 struct {
Height int64 `json:"height"`
Width int64 `json:"width"`
}
問題点
動作には何も問題がなかったのですが、私の用途では以下の点で構造体の出力形式が不十分でした。
その1
ネストしたJSONを分割して出力できるのは良いのですが、生成される名前が${nameで指定した名前}_sub${counter}
のため、
構造体の名前を一つづつ正しいものに直していかなければならない。
https://github.com/ChimeraCoder/gojson/blob/6039f74e19c1090f88a75f74700b72e539717a22/json-to-struct.go#L301
その2
ネストしたJSONの中には、中身が同一のものが存在するため重複して定義されてしまう。
また、重複して定義されていることを確認する方法が目grepしかなかった。
改良
1つ目は、多くの場合ネストする構造体の名前は呼び出し元の名前と一致するので呼び出し元の名前を使うように修正。
2つ目については、go-json側に実装すると別物になってしまうので
ネストする構造体の出力ファイルを別ファイルに吐き出し、構造体の生成後にdiff
コマンドを使う手を取りました。
実際の修正内容はこんな感じ。
https://github.com/Ladicle/gojson/pull/1/files
これを先ほどのvideo.json
に対して実行すると2つのファイルが吐き出されます。
package vimeo
type Video struct {
CreatedAt string `json:"created_at"`
ID string `json:"id"`
Size Size `json:"size"`
}
package vimeo
type Size struct {
Height int64 `json:"height"`
Width int64 `json:"width"`
}
はっぴー( ・⊝・ )
おわりに
今回は構造体に焦点を当てましたが、
実装時にはリクエストの生成やエラーハンドリング、パッケージ分割などにも悩みました。
そんな時に参考にしたのは以下のライブラリです。特にstripeはコンパクトで読みやすいのでオススメです。