Goでsql.NullStringを含む構造体をjson.Marshalする方法
以下を参考にしたがうまくできなかったので、変更点を記載。
参考
http://okamuuu.hatenablog.com/entry/2016/12/20/150339
以下の構造体 A があったとします
type A struct {
   ID    int             `json:"id"`
   Title string          `json:"title"`
   Desc  sql.NullString  `json:"desc"`
}
sql.NullString を使うケースとしては、 NULLを許容 するときです。
で、これを json.Marshal すると、
"desc" : { "String" : "", "Valid" : false }
という感じになってしまいます。
json.Marshal のソースを見ると、 MarshalJSON() というinterfaceを持っていれば、
それを実行するというふうになっています。
sql.NullString は、MarshalJSON() を持たないので、
以下のようにカスタムで NullString と言う感じの構造体を作って、それを定義してあげます。
type NullString struct {
	sql.NullString
}
func (s NullString) MarshalJSON() ([]byte, error) {
	return json.Marshal(s.String)
}
func (s *NullString) UnmarshalJSON(data []byte) error {
	var str string
	if err := json.Unmarshal(data, &str); err != nil {
		return err
	}
	s.String = str
	s.Valid = str != ""
	return nil
}
それで、今回のポイントは1つで、
func (s NullString) MarshalJSON() この部分です。
参考にした記事とかでは、
func (s *NullString) MarshalJSON()
というふうになっていて、すなわち、レシーバーがポインタになっているわけです。
このとき、jsonにしたい構造体で、
[]NullString というslice型の場合は、ちゃんと MarshalJSONを実行してくれますが、
NullString という通常の型の場合は、実行してくれません。
自分は、ここで躓きました。。
で、結局正しいのはなにかというと、
Marshalする場合は、レシーバーをポインタにしない
func (s NullString) MarshalJSON() で正しく動きます。
