いろいろ備忘録日記

主に .NET とか Go とか Flutter とか Python絡みのメモを公開しています。

Goメモ-376 (JSONのデコード時に不明なフィールドがある場合エラーとする)(DisallowUnknownFields)

関連記事

GitHub - devlights/blog-summary: ブログ「いろいろ備忘録日記」のまとめ

概要

以下、自分用のメモです。忘れないうちにメモメモ。。。

JSONのエンコード・デコードは、よくやる作業ですが、デコード時に構造体側のフィールド定義が漏れてしまっていて、値が入っていないというミスをするときがあります。

その場合は、*json.Decoder.DisallowUnknownFields() を呼んでおくと、救われるときがあったりします。

この呼び出しをしておくと、「JSON側に定義されているフィールドが、構造体側に存在しない場合にエラー」となります。

サンプル

package jsonop

import (
    "encoding/json"
    "errors"
    "io"
    "strings"

    "github.com/devlights/gomy/output"
)

// DisallowUnknownFields は、*Decoder.DisallowUnknownFields のサンプルです。
//
// # REFERENCES
//   - https://pkg.go.dev/encoding/json@go1.21.6#Decoder.DisallowUnknownFields
func DisallowUnknownFields() error {
    const (
        jsonValue = `{"id": 1, "name": "Test1", "age": 99}`
    )

    type Val struct {
        Id   int    `json:"id"`
        Name string `json:"name"`
    }

    var (
        stream = strings.NewReader(jsonValue)
        dec    = json.NewDecoder(stream)
    )

    //
    // 普通にデコード
    //
    // *json.Decoder.DisallowUnknownFields() を呼んでいないので
    // 存在しないJSONフィールドがあってもエラーにはならない。
    //
    var (
        v   Val
        err error
    )

    err = dec.Decode(&v)
    if err != nil && !errors.Is(err, io.EOF) {
        return err
    }

    output.Stdoutf("[Normal]", "%v\n", v)

    //
    // 不明なフィールドは許可しないよう設定
    //
    // この場合の「不明なフィールド」というのは
    // "JSON側に存在しているフィールドが、受け側の構造体に存在しない場合" という意味。
    // 構造体側に存在しているフィールドが、JSON側に存在しないのはエラーにならないので注意。
    //
    // 今度は、ageというJSONフィールドに対応する構造体フィールドが存在しないのでエラーとなる。
    //
    stream = strings.NewReader(jsonValue)
    dec = json.NewDecoder(stream)

    dec.DisallowUnknownFields()

    err = dec.Decode(&v)
    if err != nil && !errors.Is(err, io.EOF) {
        output.Stdoutf("[DisallowUnknownFields]", "%v(%T)", err, err)
    }

    return nil
}

実行すると以下のようになります。

$ task
task: [build] go build .
task: [run] ./try-golang -onetime

ENTER EXAMPLE NAME: json_disallow_unknown_fields

[Name] "json_disallow_unknown_fields"
[Normal]             {1 Test1}
[DisallowUnknownFields] json: unknown field "age"(*errors.errorString)

[Elapsed] 158.11µs

参考情報

https://pkg.go.dev/encoding/json@go1.21.6#Decoder

https://pkg.go.dev/encoding/json@go1.21.6#Decoder.DisallowUnknownFields

try-golang/examples/basic/jsonop/disallow_unknown_fields.go at main · devlights/try-golang · GitHub

Goのおすすめ書籍

上の書籍の日本語版が下です。


過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。