ホームページ  >  記事  >  バックエンド開発  >  Go で JSON を解析するときにデータ型を保持するにはどうすればよいですか?

Go で JSON を解析するときにデータ型を保持するにはどうすればよいですか?

DDD
DDDオリジナル
2024-11-25 02:46:10680ブラウズ

How Can I Preserve Data Types When Parsing JSON in Go?

JSON 解析におけるデータ型の保持

Golang で JSON データを解析するときに遭遇する課題の 1 つは、数値を浮動小数点数に自動的に変換することです。これにより、特に整数値を扱う場合に、元のデータとの不一致が生じる可能性があります。

この問題に対処するには、JSON 解析中にデータ型を保持するためのいくつかの手法があります。

カスタムJSON 値

1 つのアプローチは、Go が提供するカスタム JSON 値メカニズムを利用することです。これには、json.Marshaler インターフェイスと json.Unmarshaler インターフェイスを実装するカスタム タイプの作成が含まれます。 MarshalJSON メソッドと UnmarshalJSON メソッドをオーバーライドすることで、シリアル化および逆シリアル化中に数値を処理する方法を制御できます。

Go json.Number

もう 1 つのオプションは、json を使用することです。 .Go 1.8 で導入された Number 型。デフォルトでは、JSON の数値は float64 として解析されます。ただし、json.Number を使用し、Int64 メソッドまたは Float64 メソッドを呼び出すことにより、数値をそれぞれ整数または浮動小数点値に明示的に変換できます。

例実装

package main

import (
    "encoding/json"
    "fmt"
    "strconv"
    "strings"
)

type MyJSONNumber struct {
    json.Number
}

func (mn *MyJSONNumber) MarshalJSON() ([]byte, error) {
    if n, err := strconv.Atoi(string(mn.Number)); err == nil {
        return []byte(strconv.Itoa(n)), nil
    }
    return []byte(mn.Number), nil
}

func (mn *MyJSONNumber) UnmarshalJSON(b []byte) error {
    if n, err := strconv.Atoi(string(b)); err == nil {
        mn.Number = strconv.Itoa(n)
        return nil
    }
    mn.Number = string(b)
    return nil
}

func main() {
    str := `{"a":123,"b":12.3,"c":"123","d":"12.3","e":true}`
    var raw map[string]json.RawMessage
    err := json.Unmarshal([]byte(str), &raw)
    if err != nil {
        panic(err)
    }
    parsed := make(map[string]interface{}, len(raw))
    for key, val := range raw {
        s := string(val)
        jnum := MyJSONNumber{json.Number(s)}
        n, err := jnum.Int64()
        if err == nil {
            parsed[key] = n
            continue
        }
        f, err := jnum.Float64()
        if err == nil {
            parsed[key] = f
            continue
        }
        var v interface{}
        err = json.Unmarshal(val, &v)
        if err == nil {
            parsed[key] = v
            continue
        }
        parsed[key] = val
    }
    for key, val := range parsed {
        fmt.Printf("%T: %v %v\n", val, key, val)
    }
}

出力:

int64: a 123
float64: b 12.3
string: c 123
string: d 12.3
bool: e true

以上がGo で JSON を解析するときにデータ型を保持するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。