json - JSON 解码中缺失字段和空字段之间的区别

标签 json pointers go struct

所以我在 Go 中有这个结构:

type Car struct {
    Name  string `json:"name"`
    Speed int    `json:"speed"`
}

我有两个已解码的 JSON 示例:

str := `{"name": "", "speed": 0}`
strTwo := `{}`

我以这种方式进行解码:

car := Car{}
_ = json.Unmarshal([]byte(str), &car)

carTwo := Car{}
_ = json.Unmarshal([]byte(strTwo), &carTwo)

现在,由于 Go 处理默认值类型的方式,当我尝试打印结构时,我得到了相同的结果:

car - { 0}
carTwo - { 0}

所以我看不出 JSON 中缺失值和传递默认值之间的区别。我该如何解决这个问题?

一种方法是在结构中使用指针:

type Car struct {
    Name  *string `json:"name"`
    Speed *int    `json:"speed"`
}

但是在使用这个值时我得到了一个非常丑陋的代码,我必须在各处进行指针取消引用

最佳答案

Go 的原始数据类型不适合处理“所有有效值”和附加的“存在”信息。

如果您确实需要此功能,一种方法是使用指针,其中 nil 指针值对应于“缺失”状态。

如果之后使用指针感到不舒服,请执行“后处理”:将具有指针字段的结构转换为具有非指针字段的结构值,以便稍后可以使用它。

您可以“手动”执行此操作,或编写自定义解码器以自动执行此操作。

以下是如何执行此操作的示例:

type PCar struct {
    Name  *string `json:"name"`
    Speed *int    `json:"speed"`
}

type Car struct {
    Name  string `json:"-"`
    Speed int    `json:"-"`
    PCar
}

func (c *Car) UnmarshalJSON(data []byte) error {
    if err := json.Unmarshal(data, &c.PCar); err != nil {
        return err
    }

    if c.PCar.Name != nil {
        c.Name = *c.PCar.Name
    }
    if c.PCar.Speed != nil {
        c.Speed = *c.PCar.Speed
    }
    return nil
}

使用示例:

sources := []string{
    `{"name": "", "speed": 0}`,
    `{}`,
    `{"name": "Bob", "speed": 21}`,
}

for i, src := range sources {
    var c Car
    if err := json.Unmarshal([]byte(src), &c); err != nil {
        panic(err)
    }
    fmt.Println("car", i, c)
}

输出(在 Go Playground 上尝试):

car 0 { 0 {0x40c200 0x4140ac}}
car 1 { 0 {<nil> <nil>}}
car 2 {Bob 21 {0x40c218 0x41410c}}

如您所见,car 1 包含 2 个非 nil 指针,因为相应的字段存在于输入 JSON 中,而 car 2 code> 包含 2 个 nil 指针,因为这些字段在其输入中丢失。您可以使用 Car.NameCar.Speed 字段作为非指针(因为它们不是指针)。要判断它们是否存在于输入中,您可以检查相应的指针 Car.PCar.NameCar.PCar.Speed 是否为 nil.

关于json - JSON 解码中缺失字段和空字段之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56324288/

相关文章:

c++ - 为什么原始指针值被覆盖/超出范围

c - 在c中使用指针打印Char数组

c++ - 将模板化 T 定义为指针

json - Django-模板中的Json数据

javascript - Chrome 多功能框特殊字符抛出错误

rest - Go语言中的坟墓

git - 确定传入 HTTP 请求的 VCS

go - 当我将外部结构的实例传递给外部结构实现的接口(interface) slice 时,无法访问嵌入式结构

java - 清理 java 服务器的 json 输入

ios - 无法将类型 'SwiftyJSON.JSON' 的值转换为 'Swift.String'