如何以一种好的方式使用SQL NULL值和JSON?

问题描述 投票:33回答:2

[Go类型,例如Int64String无法存储空值,因此我发现可以为此使用sql.NullInt64sql.NullString

但是当我在Struct中使用它们时,并使用json包从Struct生成JSON,那么格式与我使用常规Int64String类型时的格式不同。

JSON具有附加级别,因为sql.Null ***也是结构。

是否有很好的解决方法,还是不应该在我的SQL数据库中使用NULL?

sql json go
2个回答
53
投票

sql.NullInt64之类的类型不会对JSON封送或封送进行任何特殊处理,因此适用默认规则。由于类型是结构,因此将其编组为对象,并将其字段作为属性。

解决此问题的一种方法是创建自己的类型,以实现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


11
投票

如果使用null.v3包,则无需实现任何编组或解组方法。它是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网络服务器,可以咨询this gist

© www.soinside.com 2019 - 2024. All rights reserved.