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、整数变浮点数
转载地址:https://blog.csdn.net/qq_33867131/article/details/106948156