LoginSignup
4
4

More than 5 years have passed since last update.

Goで楽なシリアル化

Posted at

最近REST APIを作るためにGoを使っていますが、きれいにデータをJSONに変換するために少し苦労していました。

ほとんどのチュートリアルや記事では、静的なstructとタグを使ってJSONを返す方法について解説しています。

type User struct {
    ID        int `json:"id"`
    Email     string `json:"email"`
    HideEmail bool `json:"hide_email"`
    FirstName string `json:"first_name"`
    LastName  string `json:"last_name"`
    CreatedAt time.Time `json:"created_at"`
    UpdatedAt time.Time `json:"updated_at"`
}

user := User{
    ID: 1, Email: "x@example.com", FirstName: "Foo", LastName:  "Bar",HideEmail: true
}

data, err := json.Marshal(user)

確かに便利ではありますが、返すデータを動的に選ぶこともかなり多いと思います。
例えばユーザがログインしているかどうか、プライバシー設定がどうなっているか、たくさん
の条件が入ってくると思います。

そういった場合は、毎回if文などでデータを生成していくのも少し冗長すぎると思ったので、そのためのライブラリを作ってみました。

例として、以上の例のstructsnake_caseに変えて、HideEmailtrueだった場合はEmailをJSONで返したくないとしたら、次のようなコードにできます。

userSerializer := structomap.New().
                             UseSnakeCase().
                             Pick("ID", "Email", "FirstName", "LastName").
                             Omit("HideEmail").
                             OmitIf(func(u interface{}) bool {
                                return u.(User).HideEmail
                            }, "Email")

一度これを作ったら、あとは

userSerializer.Transform(user)

map[string]interface{}として欲しい結果が返ってくるので、それをjson.Encodeに渡せば終わりです。この方法を使うと、配列とスライスもそのまま使えるので、[]User型の変数をuserSerializer.TransformArrayに渡せば、同じロジックで変換された[]map[string]interface{}が返ってきます。

詳細についてはプロジェクトのページをご覧ください。

4
4
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
4
4