🌱

Gin(Go)の ShouldBindJSON でリクエストをスマートに処理する方法

に公開

はじめに

初めまして、Web企業でエンジニアをしているものです。
普段、業務ではRailsを使っているのですが、最近Go言語も気になりプライベートでGinを扱った学習をしているので気になった事を初学者にも分かるように書き残したいと思います。

皆さんは、Go言語のWebフレームワーク「Gin」を使ってAPI開発を行う際、クライアントから送られたJSONリクエストを構造体にバインドする場面は多くあります。

その中でよく使われるのが ShouldBindJSONです。この記事ではその使い方と実践的なポイントを簡潔に紹介します。

ShouldBindJSONとは

ShouldBindJSONは、Ginが提供するJSONリクエストのボディGo構造体へ自動的にマッピングする関数です。

go
err := c.ShouldBindJSON(&myStruct)
  • 引数に構造体のポインタを渡す
  • JSONのフィールドと構造体のフィールド名(もしくはタグ)が一致していれば自動的に値を詰めてくれる
  • バインドに失敗した場合は err が返る

基本的な使い方

go
type LoginRequest struct {
    Email    string `json:"email" binding:"required,email"`
    Password string `json:"password" binding:"required,min=6"`
}

func LoginHandler(c *gin.Context) {
    var req LoginRequest

    if err := c.ShouldBindJSON(&req); err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error!!!": err.Error()})
        return
    }

    // バリデーション通過後の処理
    c.JSON(http.StatusOK, gin.H{"message": "Login success!!!"})
}

解説

  • binding:"required" はGinのバリデーション機能で必須チェック
  • email, min=6 なども同時にバリデーションできる
  • バリデーションエラーは err.Error() でメッセージとして取得可能

ポイント:手動パースと比較して何が良い?

手動でやる場合:

go
body, _ := ioutil.ReadAll(c.Request.Body)
json.Unmarshal(body, &req)

ShouldBindJSONの利点:

  • ioutil など使わず簡潔
  • 自動でバリデーションできる
  • 読みやすく、保守性が高い

よくあるミス

  • json:"xxx"タグが構造体に書かれていない → バインドされない
  • フィールド名の綴りミス
  • 必須項目を送らずに nil エラーになる

おわりに

ShouldBindJSON を使えば、Ginでのリクエスト処理がシンプルかつ堅牢になります。バリデーションを組み合わせることで、安全でわかりやすいAPIを簡単に構築できるため、積極的に活用しましょう。

Discussion