混合型JSONフィールドのGoでのinterface{}表現

レスポンス間で異なる型を持つJSONフィールドをGoのinterface{}(any)で処理します。型スイッチ、アサーション、安全な処理パターンを学びます。

Advanced Types

詳細な説明

混合型JSONフィールドの処理

一部のJSON APIは、コンテキストに応じて異なる型のフィールドを返します — あるレスポンスでは文字列、別のレスポンスではオブジェクトになることがあります。Goはこれを interface{}(Go 1.18以降では any にエイリアス)で処理します。

JSONの例

{
  "result": "success",
  "data": { "count": 42 },
  "meta": [1, "two", true]
}

ここで、result は文字列、data はオブジェクト、meta は混合配列です。

生成されるGo構造体

type Response struct {
    Result string        `json:"result"`
    Data   interface{}   `json:"data"`
    Meta   []interface{} `json:"meta"`
}

型スイッチパターン

interface{} 値を処理する慣用的な方法は型スイッチです:

switch v := response.Data.(type) {
case map[string]interface{}:
    fmt.Println("Object with keys:", len(v))
case string:
    fmt.Println("String value:", v)
case float64:
    fmt.Println("Number:", v)
case nil:
    fmt.Println("Null value")
}

JSONのデフォルト型マッピング

interface{} にアンマーシャリングする場合、Goは以下のデフォルトを使用します:

  • JSONオブジェクト → map[string]interface{}
  • JSON配列 → []interface{}
  • JSON文字列 → string
  • JSON数値 → float64(整数でも常に)
  • JSON真偽値 → bool
  • JSON null → nil

ベストプラクティス

  1. 具体的な型を優先 — 型が本当に変化する場合にのみ interface{} を使用します。フィールドが常にオブジェクトだとわかっている場合は構造体を定義してください。
  2. 遅延パースに json.RawMessage を使用 — 型が別のフィールドに依存する場合、まず json.RawMessage にアンマーシャリングしてから条件付きでデコードします。
  3. バリアントを文書化 — フィールドが保持できる型を説明するコメントを追加します。
type Event struct {
    Type    string          `json:"type"`
    Payload json.RawMessage `json:"payload"`
}

Type で切り替えて、Payload を正しい構造体にアンマーシャリングします。

ユースケース

StripeやGitHubのようなWebhookシステムは、イベント名によってペイロード型が異なるイベントを送信します。interface{}やjson.RawMessageを使うことで、多態的なJSONペイロードを型安全に処理できます。

試してみる — JSON to Go Struct Converter

フルツールを開く