Closed3

jsonにnullまたはinterge値が設定される時に、sql.NullInt64を使ってUnmarshal()しようとしたら、integer値の時に0になってしまったのでメモ

yuto-myuto-m

sql.NullIntを使えばjsonの値がnull または integer型の時でもいい感じに変換してくれると思っていたらそうではなかった。

経緯
apiからproject_idがinterger型またはNULLで返ってくる時に、対応する構造体のフィールドとしてProjectIDをsql.NullInt64で設定していた。
下記のコードのように「182225883」がapiから返ってきたら、構造体にUnmarshal()すると「182225883」になると思っていたが、どうやらそうはならないらしい。

Go Playground

// You can edit this code!
// Click here and start typing.
package main

import (
	"database/sql"
	"encoding/json"
	"fmt"
)

type respTimeEntry struct {
	ProjectID sql.NullInt64 `json:"project_id"`
}

func main() {
	hoge := []byte(`{"project_id": 182225883}`)

	fmt.Println(string(hoge))

	resp := respTimeEntry{}
	json.Unmarshal(hoge, &resp)

	fmt.Printf("%+v", resp)
	fmt.Println(resp.ProjectID.Int64) // 182225883になるかと思っていたけど、実際は0
	fmt.Println(resp.ProjectID.Valid) // trueになるかと思っていたけど、実際はfalse
}
yuto-myuto-m

stackoverflowにあるように、sql.Nullxxx系の型ではjsonのNULLには対応できないらしい。

I've found a nullable int64 in the sql package, but json doesn't seem to be able to handle it.

対策
下記2パターンあるけど、個人的にはnull packageを使うのがnullable intなんだなって分かりやすくて良い気がする。まあ*intでもnullable intなんだなって分かる気はするけど。

yuto-myuto-m

ちなみにsql.Nullxxx系の型でも、頑張ってMarshalJSON()とUnmarshalJSON()を書けばいい感じにjsonのNULLを扱えるぽい。

めんどくさいなっていう気がするのでやっぱりnull package使うなっていう気持ち。

このスクラップは2023/07/29にクローズされました