关于go:Go的省略符-omitempty和-两种方式详解

3次阅读

共计 2735 个字符,预计需要花费 7 分钟才能阅读完成。

一、介绍

官网文档 https://pkg.go.dev/encoding/json 有介绍

  • omitempty 如果字段的值为空值(定义为 false、0、nil 指针、nil 接口值以及任何空数组、切片、映射或字符串),该选项在编码期间疏忽该字段
  • “-“ 标签在编码和解码时总是省略字段

二、omitempty 空值省略

2.1 json 在构造体重的写法

咱们常常看到如下的构造体中,用 tag 标注了解析 json 的格局
首先咱们初始化一个空构造体 Product

package json

import (
    "encoding/json"
    "testing"
)

type Product struct {
    OrderId  string    `json:"order_id"`
    CommentS []Comment `json:"comment_s"`}

type Comment struct {
    Id      int
    Content string
}

func TestJson(t *testing.T) {p := Product{}
    s, _ := json.Marshal(p)
    t.Logf("%+v", p)
    t.Log(string(s))
}

输入如下:

{OrderId: CommentS:[]} // p 构造体
{"order_id":"","comment_s":null} // p 的 json 对象

咱们发现空构造是有值的!!!
和咱们料想的,一个空构造,对应一个空 json {}有点不一样。
是因为 go 中的构造体,都会有一个默认值的空值。
如果空值省略??
用 omitempty,代码批改如下:

package json

import (
    "encoding/json"
    "testing"
)

type Product struct {
    OrderId  string    `json:"order_id,omitempty"`
    CommentS []Comment `json:"comment_s,omitempty"`}

type Comment struct {
    Id      int
    Content string
}

func TestJson(t *testing.T) {p := Product{}
    s, _ := json.Marshal(p)
    t.Logf("%+v", p)
    t.Log(string(s))
}

输入如下:

{OrderId: CommentS:[]} // p 空构造体
{}                     // p 的空 json 对象

如果构造体外面蕴含构造体呢?如何省略,示例如下:

package json

import (
    "encoding/json"
    "testing"
)

type Product struct {
    OrderId    string    `json:"order_id,omitempty"`
    CommentS   []Comment `json:"comment_s,omitempty"`
    OneComment Comment   `json:"one_comment,omitempty"`
}

type Comment struct {
    Id      int    `json:"id"`
    Content string `json:"content"`
}

func TestJson(t *testing.T) {p := Product{}
    s, _ := json.Marshal(p)
    t.Logf("%+v", p)
    t.Log(string(s))
}

输入如下:

{OrderId: CommentS:[] OneComment:{Id:0 Content:}} // p 空构造体
{"one_comment":{"id":0,"content":""}}  // p 的空 json 对象

咱们发现 json 不再是 {}了 one_comment 还是展现了,为啥?
因为 OneComment 构造体的零值,是一个 Comment 构造体

type Comment struct {
    Id      int    `json:"id"`
    Content string `json:"content"`
}

而 Comment 的 Id,和 Content 并没有零值省略。咱们加上 omitempty

package json

import (
    "encoding/json"
    "testing"
)

type Product struct {
    OrderId    string    `json:"order_id,omitempty"`
    CommentS   []Comment `json:"comment_s,omitempty"`
    OneComment Comment   `json:"one_comment,omitempty"`
}

type Comment struct {
    Id      int    `json:"id,omitempty"`
    Content string `json:"content,omitempty"`
}

func TestJson(t *testing.T) {p := Product{}
    s, _ := json.Marshal(p)
    t.Logf("%+v", p)
    t.Log(string(s))
}

输入如下:

{OrderId: CommentS:[] OneComment:{Id:0 Content:}}
{"one_comment":{}}

咱们发现 并不是{},即便全副加上 omitempty,蕴含的

OneComment Comment   `json:"one_comment,omitempty"`

并不是{},而是 ”one_comment”:{}

还记得官网文档吗,并没有空构造体

omitempty 如果字段的值为空值(定义为 false、0、nil 指针、nil 接口值以及空数组、切片、map 或字符串),该选项在编码期间疏忽该字段

此时咱们改成 空构造变成空指针 OneComment Comment*

OneComment *Comment   `json:"one_comment,omitempty"`

变成

package json

import (
    "encoding/json"
    "testing"
)

type Product struct {
    OrderId    string    `json:"order_id,omitempty"`
    CommentS   []Comment `json:"comment_s,omitempty"`
    OneComment *Comment   `json:"one_comment,omitempty"`
}

type Comment struct {
    Id      int    `json:"id,omitempty"`
    Content string `json:"content,omitempty"`
}

func TestJson(t *testing.T) {p := Product{}
    s, _ := json.Marshal(p)
    t.Logf("%+v", p)
    t.Log(string(s))
}

输入如下:

{OrderId: CommentS:[] OneComment:<nil>}
{}   // p 的空 json
正文完
 0