golang的omitempty使用注意事项

常见用法

omitempty主要用于json 和 struct 之间的转换,忽略掉结构体结构体的0值元素

例如:

type Person struct {
 Name              string `json:"name"`
 Constellation     string `json:"constellation,omitempty"`
 Age               uint32 `json:"age"`
}

type PersonOmite struct {
 Name              string `json:"name"`
 Constellation     string `json:"constellation,omitempty"`
 Age               uint32 `json:"age"`
}


data := `{
  "name": "zhang san",
  "Age": 30
 }`
 per := new(Person)
 json.Unmarshal([]byte(data), &per)

 perBytes, _ := json.MarshalIndent(per, "", "    ")
 fmt.Printf("%s\n", string(perBytes))

 perOm := new(PersonOmite)
 json.Unmarshal([]byte(data), &perOm)


 perOmBytes, _ := json.MarshalIndent(perOm, "", "    ")
 fmt.Printf("%s\n", string(perOmBytes))


//得到的结果
{
    "name": "zhang san",
    "constellation":"",
    "age": 30
}

{
    "name": "zhang san",
    "age": 30
}

坑1

带来方便的同时,使用 omitempty 也有些小陷阱,一个是该关键字无法忽略掉嵌套结构体。还是拿地址类型说事,这回我们想要往地址结构体中加一个新 field 来表示经纬度,如果缺乏相关的数据,暂时可以忽略。新的结构体定义如下所示

type address struct {
 Street     string     `json:"street"`
 Ste        string     `json:"suite,omitempty"`
 City       string     `json:"city"`
 State      string     `json:"state"`
 Zipcode    string     `json:"zipcode"`
 Coordinate coordinate `json:"coordinate,omitempty"`
}

type coordinate struct {
 Lat float64 `json:"latitude"`
 Lng float64 `json:"longitude"`
}

读入原来的地址数据,处理后序列化输出,我们就会发现即使加上了 omitempty 关键字,输出的 json 还是带上了一个空的坐标信息

{
    "street": "200 Larkin St",
    "city": "San Francisco",
    "state": "CA",
    "zipcode": "94102",
    "coordinate": {
        "latitude": 0,
        "longitude": 0
    }
}

为了达到我们想要的效果,可以把坐标定义为指针类型,这样 Golang 就能知道一个指针的“空值”是多少了,否则面对一个我们自定义的结构, Golang 是猜不出我们想要的空值的。于是有了如下的结构体定义

type address struct {
 Street     string      `json:"street"`
 Ste        string      `json:"suite,omitempty"`
 City       string      `json:"city"`
 State      string      `json:"state"`
 Zipcode    string      `json:"zipcode"`
 Coordinate *coordinate `json:"coordinate,omitempty"`
}

type coordinate struct {
 Lat float64 `json:"latitude"`
 Lng float64 `json:"longitude"`
}

相应的输出为

{
    "street": "200 Larkin St",
    "city": "San Francisco",
    "state": "CA",
    "zipcode": "94102"
}

坑2

另一个“陷阱”是,对于用 omitempty 定义的 field ,如果给它赋的值恰好等于默认空值的话,在转为 json 之后也不会输出这个 field 。比如说上面定义的经纬度坐标结构体,如果我们将经纬度两个 field 都加上 omitempty

type coordinate struct {
 Lat float64 `json:"latitude,omitempty"`
 Lng float64 `json:"longitude,omitempty"`
}

然后我们对非洲几内亚湾的“原点坐标”非常感兴趣,于是编写了如下代码

func main() {
 cData := `{
  "latitude": 0.0,
  "longitude": 0.0
 }`
 c := new(coordinate)
 json.Unmarshal([]byte(cData), &c)

  // 具体处理逻辑...

 coordinateBytes, _ := json.MarshalIndent(c, "", "    ")
 fmt.Printf("%s\n", string(coordinateBytes))
}

最终我们得到了一个

{}

这个坐标消失不见了!但我们的设想是,如果一个地点没有经纬度信息,则悬空,这没有问题,但对于“原点坐标”,我们在确切知道它的经纬度的情况下,(0.0, 0.0)仍然被忽略了。正确的写法也是将结构体内的定义改为指针

type coordinate struct {
 Lat *float64 `json:"latitude,omitempty"`
 Lng *float64 `json:"longitude,omitempty"`
}

这样空值就从 float64 的 0.0 变为了指针类型的 nil ,我们就能看到正确的经纬度输出。

{
    "latitude": 0,
    "longitude": 0
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值