在Golang中为JSON字段而不是空字符串分配null

Pra*_*ant 33 go

由于空字符串是Golang的零/默认值,因此string我决定将所有这些字段定义为interface{}相反.例如

type student struct {
    FirstName  interface{} `json:"first_name"`
    MiddleName interface{} `json:"middle_name"`
    LastName   interface{} `json:"last_name"`
}
Run Code Online (Sandbox Code Playgroud)

如果该特定字段的值不可用,则我发送数据的应用程序需要null而不是空字符串.

这是正确的方法还是有人可以指点我比这更好的东西.

Asd*_*ine 59

json包文档中:

指针值编码为指向的值.nil指针编码为null JSON对象.

所以你可以存储一个指向字符串的指针,如果不是nil将被编码为字符串,如果为nil将被编码为"null"

type student struct {
  FirstName  *string `json:"first_name"`
  MiddleName *string `json:"middle_name"`
  LastName   *string `json:"last_name"`
}
Run Code Online (Sandbox Code Playgroud)

  • 我会说可读性和一致性.很明显,通过指向字符串的方法,您可以知道var的内容.使用接口告诉编译器FirstName可以是任何东西,并为错误留出空间 (4认同)
  • @stanley_manley 这种方法对我来说非常适合“float64”。 (2认同)

小智 8

可以使用https://github.com/guregu/null

type student struct {
FirstName  null.String `json:"first_name"`
MiddleName null.String `json:"middle_name"`
LastName   null.String `json:"last_name"`}
Run Code Online (Sandbox Code Playgroud)

  • @Dragonthoughts 站外资源?他正在链接到 Github 上的一个项目,这是一件非常合适的事情。 (9认同)
  • 确实如此,但如果 github 存储库消失了,go 库也会随之消失 (3认同)

ini*_*nix 7

您可以使用sql.NullString之类的东西,使用 'Valid' 来检查它是否为 nil 值。

NullString 表示可能为空的字符串。NullString 实现 Scanner 接口,因此它可以用作扫描目标:

type NullString struct {
    String string
    Valid  bool // Valid is true if String is not NULL
}

var s NullString
err := db.QueryRow("SELECT name FROM foo WHERE id=?", id).Scan(&s)
...
if s.Valid {
   // use s.String
} else {
   // NULL value
}
Run Code Online (Sandbox Code Playgroud)

不要使用如下指针:

type student struct {
  FirstName  *string `json:"first_name"`
  MiddleName *string `json:"middle_name"`
  LastName   *string `json:"last_name"`
}
Run Code Online (Sandbox Code Playgroud)

因为你需要检查 nil 值并像下面这样到处取消引用,并且可能会在某处导致意外崩溃:

if obj.FirstName != nil {
   fmt.Print("%s", *obj.FirstName)
}
Run Code Online (Sandbox Code Playgroud)

我比较了两种解决方案,并在我广泛的生产代码中选择前一种方法......它工作正常。


小智 6

另一种方法实际上是使用 golang 的 json 库提供的 MarhshalJSON 和 UnmarshalJSON 接口方法的解决方法。代码如下:

type MyType string
type MyStruct struct {
    A MyType `json:"my_type"`
}

func (c MyType) MarshalJSON() ([]byte, error) {
    var buf bytes.Buffer
    if len(string(c)) == 0 {
        buf.WriteString(`null`)
    } else {
        buf.WriteString(`"` + string(c) + `"`)   // add double quation mark as json format required
    }
    return buf.Bytes(), nil
}

func (c *MyType)UnmarshalJSON(in []byte) error {
    str := string(in)
    if str == `null` {
        *c = ""
        return nil
    }
    res := MyType(str)
    if len(res) >= 2 {
        res = res[1:len(res)-1]     // remove the wrapped qutation
    }
    *c = res
    return nil
}
Run Code Online (Sandbox Code Playgroud)

那么当使用 json.Marshal 时,MyType 值将被编组为 null。


Ati*_*ifm 5

对于带有空字符串的 json 对象,最容易在字段上使用 omitempty 装饰器。

type student struct {
  FirstName  string `json:"first_name,omitempty"`
  MiddleName string `json:"middle_name,omitempty"`
  LastName   string `json:"last_name"`
}
Run Code Online (Sandbox Code Playgroud)

使用上面的声明,仅当分配了 first_name 时,该键才会显示在结果 json 中。另一方面,如果未分配,last_name 将始终显示在结果中,其值为“”。

现在,当您开始包含 0 可能是值的数字字段时,使用 omitempty 并不能满足人们的预期。0 值总是丢弃该字段,我们需要能够区分 0 值和未分配的值。在这里使用诸如此类的库https://github.com/guregu/null可能是可取的。

更多讨论在这里:https : //www.sohamkamani.com/blog/golang/2018-07-19-golang-omitempty/