golang结构体tag的使用

tag是结构体的元信息,可以在运行的时候通过反射机制读取出来
1、tag定义格式:(tag在结构体字段的后方定义,由一对反引号包裹起来,不同的键值对之间使用空格分隔)
    `key1:"value1" key2:"value2"`
2、指定字段名(序列化与反序列化默认情况下使用结构体的字段名,我们可以通过给结构体字段添加tag来指定json序列化生成的字段名)
   // 使用json tag指定json序列化与反序列化时的行为
    type Person struct {
    	Name   string `json:"name"` // 指定json序列化/反序列化时使用小写name
    	Age    int64
    	Weight float64
    }
3、忽略某个字段(如果你想在json序列化/反序列化的时候忽略掉结构体中的某个字段)
    // 使用json tag指定json序列化与反序列化时的行为
    type Person struct {
    	Name   string `json:"name"` // 指定json序列化/反序列化时使用小写name
    	Age    int64
    	Weight float64 `json:"-"` // 指定json序列化/反序列化时忽略此字段
    }
4、忽略空值字段
    当 struct 中的字段没有值时, json.Marshal() 序列化的时候不会忽略这些字段,而是默认输出字段的类型零值
    (例如int和float类型零值是 0,string类型零值是"",对象类型零值是 nil)。
    如果想要在序列序列化时忽略这些没有值的字段时,可以在对应字段添加omitempty tag。
    // 在tag中添加omitempty忽略空值
    // 注意这里 hobby,omitempty 合起来是json tag值,中间用英文逗号分隔
    type User struct {
    	Name  string
    	Email string   `json:"email,omitempty"`
    	Hobby []string `json:"hobby,omitempty"`
    }
    func main() {
    	user := User{
    		Name: "小神童",
    	}
    	// struct -> json string
    	str_user, err := json.Marshal(user)
    	if err != nil {
    		fmt.Printf("json.Marshal failed, err:%v\n", err)
    		return
    	}
    	fmt.Printf("str_user:%s\n", str_user)
    	// 打印结果   str_user:{"Name":"小神童"}
    	// 如果不设置omitempty  str_user:{"Name":"小神童","Email":"","Hobby":null}
    }
5、结构体嵌套空值字段处理
type Person struct {
	Age    int64   `json:"age"`
	Height float64 `json:"height"`
	Weight float64 `json:"Weight"`
}
type User struct {
	Name  string   `json:"name"`
	Email string   `json:"email,omitempty"`
	Hobby []string `json:"hobby,omitempty"`
	Person
}
func main() {
	user := User{
		Name:  "小神童",
		Hobby: []string{"足球", "篮球"},
	}
	str_user, err := json.Marshal(user)
	if err != nil {
		fmt.Printf("json.Marshal failed, err:%v\n", err)
		return
	}
	// 打印结果: str_user:{"name":"小神童","hobby":["足球","篮球"],"age":0,"height":0,"Weight":0}
	fmt.Printf("str_user:%s\n", str_user)

	// (1)嵌套Person序列化后的json串为单层,想要变成嵌套的json串,需要改为具名嵌套
	//	type User struct {
	//		Name  string   `json:"name"`
	//		Email string   `json:"email,omitempty"`
	//		Hobby []string `json:"hobby,omitempty"`
	//		Person         `json:"person"`     // 给字段定义一个tag名
	//	}
	//  打印结果  str_user:{"name":"小神童","hobby":["足球","篮球"],"person":{"age":0,"height":0,"Weight":0}}

	// (2)想要在嵌套的结构体为空值时,忽略该字段,仅添加omitempty是不够的,还需要使用嵌套结构体的指针
	//	type User struct {
	//		Name  string   `json:"name"`
	//		Email string   `json:"email,omitempty"`
	//		Hobby []string `json:"hobby,omitempty"`
	//		*Person        `json:"person,omitempty"`
	//	}
	// 打印结果 str_user:{"name":"小神童","hobby":["足球","篮球"]}
}
6、我们需要json序列化User,但是不想把密码也序列化,又不想修改User结构体
   我们可以创建另外一个结构体PublicUser,嵌套原User,同时指定Password字段为结构体指针类型,并添加omitempty tag
    示例如下:
    type User struct {
        Name     string `json:"name"`
        Password string `json:"password"`
    }
    type PublicUser struct {
        *User             	// 匿名嵌套User
        Password *struct{} `json:"password,omitempty"`
    }
    func main() {
        user := User{
            Name:     "小神童",
            Password: "123456",
        }
        str_user, err := json.Marshal(PublicUser{User: &user})
        if err != nil {
            fmt.Printf("json.Marshal u1 failed, err:%v\n", err)
            return
        }
        // 序列化结果 str_user:{"name":"小神童"}
        fmt.Printf("str_user:%s\n", str_user)
    }
7、优雅处理字符串格式的数字
    前端在传递来的json数据中可能会使用字符串类型的数字,这个时候可以在结构体tag中添加string来告诉json包从字符串中解析相应字段的数据
    type Card struct {
        ID    int64   `json:"id,string"`    // 添加string tag
        Score float64 `json:"score,string"` // 添加string tag
    }
    func main() {
        str_json := `{"id": "123","score": "22.22"}`
        var card Card
        if err := json.Unmarshal([]byte(str_json), &card); err != nil {
            fmt.Printf("json.Unmarsha jsonStr1 failed, err:%v\n", err)
            return
        }
        // 打印结果:card:main.Card{ID:1234567, Score:88.5}
        fmt.Printf("card:%#v\n", card)
    }
8、整数变浮点数

 

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页