16
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Go (その2)Advent Calendar 2016

Day 4

APIライブラリをgo-json(改)で楽に実装する

Last updated at Posted at 2016-12-04

はじめに

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で出力先です

generate-struct.sh
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{...}ではなく別の構造体に分割されます

video.json
{
  "id": "2321232",
  "created_at": "2016/12/24",
  "size": {
    "width": 400,
    "height": 860
  }
}
video.go
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つのファイルが吐き出されます。

00_video.go
package vimeo

type Video struct {
	CreatedAt string `json:"created_at"`
	ID        string `json:"id"`
	Size      Size   `json:"size"`
}
01_video.go
package vimeo

type Size struct {
	Height int64 `json:"height"`
	Width  int64 `json:"width"`
}

はっぴー( ・⊝・ )

おわりに

今回は構造体に焦点を当てましたが、
実装時にはリクエストの生成やエラーハンドリング、パッケージ分割などにも悩みました。
そんな時に参考にしたのは以下のライブラリです。特にstripeはコンパクトで読みやすいのでオススメです。

16
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?