JSON数値の処理 — Goでのint vs float64
GoがJSON数値をどう処理するかを理解します。int、float64、json.Numberの使い分け。精度の問題、大きな整数、数値文字列のパースを解説。
Edge Cases
詳細な説明
GoでのJSON数値型
JSONには単一の number 型がありますが、Goは int、int64、float64 などを区別します。正確性と精度のために適切な型を選ぶことが重要です。
デフォルトの動作
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の数値処理を理解することで、微妙なデータ破損バグを防げます。