page contents

详谈Golang-json的使用(json tag)

详谈Golang-json的使用(json tag) 结构体的tag tag是结构体的元信息,运行时通过反射机制读取。结构体的tag一般定义在相应字段的后面,格式为: fieldName fieldType  `key1:"value1" ke...

attachments-2021-07-6eYRjSiE60f7872ea6fa5.png

详谈Golang-json的使用(json tag)

结构体的tag

tag是结构体的元信息,运行时通过反射机制读取。结构体的tag一般定义在相应字段的后面,格式为:

fieldName fieldType  `key1:"value1" key2:"value2"

同一个结构体字段可以设置多个键值对tag,不同的键值对之间使用空格分隔。

json tag

默认情况下序列化与反序列化使用的都是结构体的原生字段名,可以通过给结构体字段添加json tag来指定序列化后的字段名。

例如代码:

package main
import (
"fmt"
"encoding/json"
)
type Student struct {
Name   string  `json:"name"`
Age    int64
Weight float64
Height float64
}
func main() {
s1 := Student{
Name:   "jack",
Age:    20,
Weight: 71.5,
Height: 172.5,
}
b, err := json.Marshal(s1)
if err != nil {
fmt.Printf("json.Marshal failed, err:%v\n", err)
return
}
fmt.Printf("s1: %s\n", b)
var s2 Student
err = json.Unmarshal(b, &s2)
if err != nil {
fmt.Printf("json.Unmarshal failed, err:%v\n", err)
return
}
fmt.Printf("s2: %#v\n", s2)
}

输出:

s1: {"name":"jack","Age":20,"Weight":71.5,"Height":172.5}
s2: main.Student{Name:"jack", Age:20, Weight:71.5, Height:172.5}

使用json tag序列化时忽略任一字段

使用“-”作为相应字段json tag的value值,如:

type Student struct {
Name   string  `json:"name"`
Age    int64
Weight float64  `json:"-"`
Height float64
}

输出:

s1: {"name":"jack","Age":20,"Height":172.5}
s2: main.Student{Name:"jack", Age:20, Weight:0, Height:172.5}

注:反序列化时仍将恢复该字段,零值处理。

使用json tag序列化时忽略普通结构体中的为空字段

使用“omitempty”作为相应字段json tag的value值,注意此时在“omitempty”前一定指定一个字段名,否则“omitempty”将作为字段名处理。如:

type Student struct {
Name   string  `json:"name"`
Age    int64
Weight float64  `json:"weight,omitempty"`
Height float64
}

此时如果这样初始化s1:

    s1 := Student{
Name:   "jack",
Age:    20,
Height: 172.5,
}

输出:

s1: {"name":"jack","Age":20,"Height":172.5}
s2: main.Student{Name:"jack", Age:20, Weight:0, Height:172.5}

可见,空字段Weight在序列化时被忽略掉了。

如果这样初始化s1:

    s1 := Student{
Name:   "jack",
Age:    20,
Weight: 0,
Height: 172.5,
}

输出:

s1: {"name":"jack","Age":20,"Height":172.5}
s2: main.Student{Name:"jack", Age:20, Weight:0, Height:172.5}

可见,使用“omitempty”的字段为零值时在序列化结果中也被忽略掉了。

使用json tag 忽略嵌套结构体中的为空字段

由于具名嵌套结构体与匿名嵌套结构体在序列化后只存在是否摊平的区别,这里不做细致讨论,使用匿名嵌套结构体(这里注:若使用匿名嵌套结构体,但同时使用json tag为该被嵌套结构体指定了字段名,序列化结果该被嵌套结构体不会被摊平)。

若要在被嵌套结构体中的某一字段为空时使其在序列化结果中被忽略,操作方法与上方普通结构体中字段一致。

若要在被嵌套结构体整体为空时使其在序列化结果中被忽略,不仅要在被嵌套结构体字段后加上json:"fileName,omitempty",还要将其改为结构体指针。如:

type BodyInfo struct {
Weight float64    
Height float64
}
type Student struct {
Name   string  `json:"name"`
Age    int64
    *BodyInfo       `json:"bodyinfo,omitempty"`
}

此时s1为:

    s1 := Student{
Name:   "jack",
Age:    20,
}

输出:

s1: {"name":"jack","Age":20}
s2: main.Student{Name:"jack", Age:20, BodyInfo:(*main.BodyInfo)(nil)}

不修改原结构体忽略某字段

需要创建另外一个结构体来匿名嵌套原结构体,同时指定待忽略字段为匿名结构体指针类型,并添加omitempty的json tag。如:

package main
import (
"fmt"
"encoding/json"
)
type Student struct {
Name   string  `json:"name"`
Age    int64   `json:"age"`
Weight float64
Height float64
}
type PStudent struct {
*Student
Age *struct{}   `json:"age,omitempty"`
}
func main() {
s1 := Student{
Name:   "jack",
Age:    20,
Weight: 61.5,
Height: 172.5,
}
ps1 := PStudent{
Student: &s1,
}
b, err := json.Marshal(ps1)
if err != nil {
fmt.Printf("json.Marshal failed, err:%v\n", err)
return
}
fmt.Printf("s1: %s\n", b)
var s2 PStudent
err = json.Unmarshal(b, &s2)
if err != nil {
fmt.Printf("json.Unmarshal failed, err:%v\n", err)
return
}
fmt.Printf("s2.student: %#v s2.age: %v\n", *s2.Student, s2.Age)
}

输出:

s1: {"name":"jack","Weight":61.5,"Height":172.5}
s2.student: main.Student{Name:"jack", Age:0, Weight:61.5, Height:172.5} s2.age: <nil>

更多相关技术内容咨询欢迎前往并持续关注六星社区了解详情。

程序员编程交流QQ群:805358732

如果你想用Python开辟副业赚钱,但不熟悉爬虫与反爬虫技术,没有接单途径,也缺乏兼职经验
关注下方微信公众号:Python编程学习圈,获取价值999元全套Python入门到进阶的学习资料以及教程,还有Python技术交流群一起交流学习哦。

attachments-2022-06-XpfslxoT62ad446b34175.jpeg

  • 发表于 2021-07-21 10:35
  • 阅读 ( 681 )
  • 分类:Golang

0 条评论

请先 登录 后评论
轩辕小不懂
轩辕小不懂

2403 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 1470 文章
  3. Pack 1135 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章