JSON数値の処理 — Goでのint vs float64

GoがJSON数値をどう処理するかを理解します。int、float64、json.Numberの使い分け。精度の問題、大きな整数、数値文字列のパースを解説。

Edge Cases

詳細な説明

GoでのJSON数値型

JSONには単一の number 型がありますが、Goは intint64float64 などを区別します。正確性と精度のために適切な型を選ぶことが重要です。

デフォルトの動作

interface{} にアンマーシャリングする場合、すべてのJSON数値は float64 になります:

var data map[string]interface{}
json.Unmarshal([]byte(`{"id": 9007199254740993}`), &data)
// data["id"] は float64、精度が失われる!

float64 は2^53までの整数のみ正確に表現できます。より大きなID(TwitterのスノーフレークIDなど)は精度を失います。

json.Numberの使用

decoder := json.NewDecoder(reader)
decoder.UseNumber()

UseNumber() を使うと、JSON数値は元のテキストを保持する json.Number(文字列型)としてアンマーシャリングされます:

n := data["id"].(json.Number)
id, _ := n.Int64()  // 精度が保たれる

型選択ガイド

JSON値 Go型 使用場面
42 int 小さな整数、カウント、ID
9007199254740993 int64 大きな整数、タイムスタンプ
3.14 float64 小数、座標
"42" string タグ付き int 文字列として送信される数値
任意の数値 json.Number 生のテキストが必要な場合

構造体フィールドの型

type Transaction struct {
    ID     int64   `json:"id"`
    Amount float64 `json:"amount"`
    Count  int     `json:"count"`
}

コンバーターはサンプルJSONを分析します:小数点付きの数値は float64 に、整数は int になります。非常に大きな数値は int64 をトリガーする場合があります。

文字列としての数値

一部のAPIは数値をクォートします:"amount": "19.99"string タグオプションを使用します:

Amount float64 `json:"amount,string"`

精度が重要なアプリケーション

金融データの場合、float64 の使用を完全に避けてください。文字列表現をパースし、任意精度ライブラリを使用するか、セントを int64 として保存します。

ユースケース

ソーシャルメディアプラットフォームはfloat64の精度を超える64ビットスノーフレークIDを使用します。金融APIは丸めを避けるために金額を文字列として送信します。Goの数値処理を理解することで、微妙なデータ破損バグを防げます。

試してみる — JSON to Go Struct Converter

フルツールを開く