golang 中的 json 标签使用
golang 的结构体可以在字段里加 tag,网上资料又看到一句“运行时”通过反射机制读取?这还没研究过,就刚好有需求的时候查一下,记录下遇到的问题和对应的tag使用吧
导出字段名
golang 中结构体,如果要导出(包括序列化、反序列化等),字段名是要大写开头的嘛,一开始没注意,反正就这样定义的结构体
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
type FwItem struct {
ID int `gorm:"column:id;primary_key"`
TypeID int `gorm:"column:typeid"`
Url string `gorm:"column:url"`
Hash string `gorm:"column:hash"`
Name string `gorm:"column:name"`
ChangeLog string `gorm:"column:changelog"`
Size int64 `gorm:"column:size"`
Serv int `gorm:"column:serv"`
ModelID int
localPath string
fileType int
tf *TempFile
}
|
但是这样,用 json.Marshal() 导出的字节数组,再用 string() 输出的字符串是大写开头的,就跟定义里字段名一致
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
{
"2": {
"ChangeLog": "just a change log",
"Hash": "9BF539D9E1448274992D004A00B994F5",
"ID": 2,
"ModelID": 0,
"Name": "bookinfo3748.json",
"Serv": 13,
"Size": 109234,
"TypeID": 1,
"Url": "/fileserv/bin/20220922/20/49/3/bookinfo3748.json"
},
"3": {
"ChangeLog": "just two change logs",
"Hash": "D9F34BB709D97A70F50AB9C6EFB882B2",
"ID": 3,
"ModelID": 0,
"Name": "Education.html",
"Serv": 13,
"Size": 28307,
"TypeID": 2,
"Url": "/fileserv/bin/20220922/20/54/3/Education.html"
}
}
|
要说这样也是没问题的,但是客户端同事说这玩意要小写,我要是字段名起的小写那怎么导出嘛,所以就要加 json tag 了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
type FwItem struct {
ID int `gorm:"column:id;primary_key" json:"id"`
TypeID int `gorm:"column:typeid" json:"type_id"`
Url string `gorm:"column:url" json:"url"`
Hash string `gorm:"column:hash" json:"hash"`
Name string `gorm:"column:name" json:"name"`
ChangeLog string `gorm:"column:changelog" json:"changelog"`
Size int64 `gorm:"column:size" json:"size"`
Serv int `gorm:"column:serv" json:"serv"`
ModelID int `gorm:"-" json:"model_id"`
localPath string
fileType int
tf *TempFile
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
{
"2": {
"changelog": "just a change log",
"hash": "9BF539D9E1448274992D004A00B994F5",
"id": 2,
"model_id": 0,
"name": "bookinfo3748.json",
"serv": 13,
"size": 109234,
"type_id": 1,
"url": "/fileserv/bin/20220922/20/49/3/bookinfo3748.json"
},
"3": {
"changelog": "just two change logs",
"hash": "D9F34BB709D97A70F50AB9C6EFB882B2",
"id": 3,
"model_id": 0,
"name": "Education.html",
"serv": 13,
"size": 28307,
"type_id": 2,
"url": "/fileserv/bin/20220922/20/54/3/Education.html"
}
}
|
然后导出的字段就是小写了,然后有了下一个问题
有些字段并不需要被序列化出来
在写相关有很多字段的 CURD 接口时,要是每个字段都从post请求里面一个个取出来,再校验,那可太麻烦了,而且又臭又长,垃圾才用的垃圾写法🤡
请求上传的时候整一个 json 参数反序列化成结构实例,实例再通过 gorm:“column:xxx” 就简单好多了,但是有这样的情况,我需要这个字段在反序列化的时候使用(定义的时候字段名大写),在序列化的时候不使用(小写的字段名肯定不被序列化),没法又大写又小写,那不精神分裂嘛
gorm 是有这个 "-" 标签的,就是显式地忽略这个字段,json 果然也有这个用法,而且有个 omitempty ,有些字段是空值,就没必要序列化了(ModelID字段是从网络请求中反序列化后的,加了 gorm:"-" 不保存到数据库,所以从数据库反序列化必然是空值的,序列化完也没意义,但是我在上传的时候又需要这个参数)刚好满足这个需求
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
type Fw__Item struct {
ID int `gorm:"column:id;primary_key" json:"id"`
TypeID int `gorm:"column:typeid" json:"type_id"`
Url string `gorm:"column:url" json:"-"`
Hash string `gorm:"column:hash" json:"-"`
Name string `gorm:"column:name" json:"name"`
ChangeLog string `gorm:"column:changelog" json:"changelog"`
Size int64 `gorm:"column:size" json:"-"`
Serv int `gorm:"column:serv" json:"-"`
ModelID int `gorm:"-" json:"model_id,omitempty"`
localPath string
fileType int
tf *TempFile
}
|
这个导出就很干净了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
{
"2": {
"changelog": "just a change log",
"id": 2,
"name": "bookinfo3748.json",
"type_id": 1
},
"3": {
"changelog": "just two change logs",
"id": 3,
"name": "Education.html",
"type_id": 2
}
}
|
还有暂时没用到的标签用法,也记录一下吧,会用上的
inline 用于内嵌的结构体
定义两个结构体,Outer嵌套Project
1
2
3
4
5
6
7
8
9
10
|
type Project struct {
Key string `json:"key"`
Value string `json:"value"`
}
type Outer struct {
Project `json:"project"`
Summary string `json:"summary"`
Desc string `json:"desc"`
}
|
打印得序列化一个结构体的json如下:
1
2
3
4
5
6
7
8
|
{
"project": {
"key": "name",
"value": "坤坤"
},
"summary": "ikun summary",
"desc": "ikun desc"
}
|
将Outer内Project字段的tag改为 ‘Project json:",inline"
‘,再次打印相同结构体的序列化得json如下:
1
2
3
4
5
6
|
{
"key": "name",
"value": "坤坤",
"summary": "ikun summary",
"desc": "ikun desc"
}
|
相比之前的json,加了inline之后project字段被展开了
尝试一下展开的json能不能反序列化回去
1
2
3
4
5
6
7
8
9
|
var outer Outer
ori := "{\"key\":\"name\",\"value\":\"坤坤\",\"summary\":\"ikun summary\",\"desc\":\"ikun desc\"}"
err := json.Unmarshal([]byte(ori), &outer)
if err != nil {
fmt.Println(err)
} else {
fmt.Println(outer)
fmt.Println(outer.Project)
}
|
output:
1
2
|
{{name 坤坤} ikun summary ikun desc}
{name 坤坤}
|
指定string,number和boolean类型反序列化
没空写了,有空再试下补充