LoginSignup
8
6

More than 5 years have passed since last update.

Goでsql.NullStringを含む構造体をjson.Marshalする方法

Posted at

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() で正しく動きます。

以上!

8
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
6