How can I work with SQL NULL values and JSON in a good way?

前端 未结 2 1467
有刺的猬
有刺的猬 2020-12-05 02:21

Go types like Int64 and String cannot store null values, so I found I could use sql.NullInt64 and sql.NullString for this.

But when I use t

相关标签:
2条回答
  • 2020-12-05 02:41

    Types like sql.NullInt64 do not implement any special handling for JSON marshaling or unmarshaling, so the default rules apply. Since the type is a struct, it gets marshalled as an object with its fields as attributes.

    One way to work around this is to create your own type that implements the json.Marshaller / json.Unmarshaler interfaces. By embedding the sql.NullInt64 type, we get the SQL methods for free. Something like this:

    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
    }
    

    If you use this type in place of sql.NullInt64, it should be encoded as you expect.

    You can test this example here: http://play.golang.org/p/zFESxLcd-c

    0 讨论(0)
  • 2020-12-05 02:50

    If you use the null.v3 package, you won't need to implement any of the marshal or unmarshal methods. It's a superset of the sql.Null structs and is probably what you want.

    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
    }
    

    If you'd like to see a full Golang webserver that uses sqlite, nulls, and json you can consult this gist.

    0 讨论(0)
提交回复
热议问题