web-dev-qa-db-ja.com

GolangでSQL NULL値とJSONを良い方法でどのように扱うことができますか?

Int64StringなどのGo型はnull値を格納できないため、このために sql.NullInt64 および sql.NullString を使用できることがわかりました。

しかし、これらをStructで使用し、 json パッケージを使用してStructからJSONを生成すると、通常のInt64およびStringタイプを使用する場合と形式が異なります。

Sql.Null ***も構造体であるため、JSONには追加のレベルがあります。

これには良い回避策がありますか、またはSQLデータベースでNULLを使用しないでください?

31
Alex

sql.NullInt64などの型は、JSONマーシャリングまたはアンマーシャリングの特別な処理を実装しないため、デフォルトのルールが適用されます。型は構造体であるため、属性としてフィールドを持つオブジェクトとしてマーシャリングされます。

これを回避する1つの方法は、json.Marshaller/json.Unmarshalerインターフェイスを実装する独自の型を作成することです。 sql.NullInt64型を埋め込むことで、SQLメソッドを無料で入手できます。このようなもの:

type JsonNullInt64 struct {
    sql.NullInt64
}

func (v JsonNullInt64) MarshalJSON() ([]byte, error) {
    if v.Valid {
        return json.Marshal(v.Int64)
    } else {
        return json.Marshal(nil)
    }
}

func (v *JsonNullInt64) UnmarshalJSON(data []byte) error {
    // Unmarshalling into a pointer will let us detect null
    var x *int64
    if err := json.Unmarshal(data, &x); err != nil {
        return err
    }
    if x != nil {
        v.Valid = true
        v.Int64 = *x
    } else {
        v.Valid = false
    }
    return nil
}

sql.NullInt64の代わりにこのタイプを使用する場合、期待どおりにエンコードする必要があります。

ここでこの例をテストできます: http://play.golang.org/p/zFESxLcd-c

48

null.v パッケージを使用する場合、マーシャリングまたはアンマーシャリングのメソッドを実装する必要はありません。これはsql.Null構造体のスーパーセットであり、おそらく必要なものです。

package main

import "gopkg.in/guregu/null.v3"

type Person struct {
    Name     string      `json:"id"`
    Age      int         `json:"age"`
    NickName null.String `json:"nickname"` // Optional
}

Sqlite、null、およびjsonを使用する完全なGolang Webサーバーを表示する場合は、 this Gist を参照してください。

8
Stephen Wood