一、sturct json tag的使用
1.tag格式说明
struct json tag主要在struct与json数据转换的过程(Marshal/Unmarshal)中使用。
json的tag格式如下:
Key type `json:"name,opt1,opt2,opts..."`
说明:
- 变量必须是可导出的(Key首字母必须大写),否则会被忽略处理。
- 没有json tag或者tag中name省略(但不能少了","),默认使用字段名。
- name要注意命名的有效性。
- opt1、opt2等项为可选项,必须使用有限的几个限定的opt的一个或组合,如"omitempty"、"string",使用非限定的opt会发生错误。
2.具体使用格式说明
我们先介绍下源码文档中提供的几种使用方式:
因Marshal与Unmarshal是相反的过程,两者规则是一致的,以下介绍中仅说明了Marshal时的处理。
(1)不指定tag
Field int // “Filed”:0
不指定tag,默认使用变量名称。转换为json时,key为Filed。
(2)直接忽略
Field int json:"-" //注意:必须为"-",不能带有opts
转换时不处理。
(3)指定key名
Field int json:"myName" // “myName”:0
转换为json时,key为myName
(4)"omitempty"零值忽略
Field int json:",omitempty"
转换为json时,值为零值则忽略,否则key为myName
(5)指定key且零值忽略
Field int json:"myName,omitempty"
转换为json时,值为零值则忽略,否则key为myName
(6)指定key为"-"
Field int json:"-," // “-”:0
此项与忽略的区别在于多了个”,“。
(7)“string” opt
以上提到的用法都是常见的,这个比较特殊。
"string"仅适用于字符串、浮点、整数或布尔类型,表示的意思是:将字段的值转换为字符串;解析时,则是将字符串解析为指定的类型。主要用于与javascript通信时数据的转换。
注意:
仅且仅有"string",没有int、number之类的opt。即带"string" opt的字段,编码时仅能将字符串、浮点、整数或布尔类型转换为string类型,反之则不然;解码时可以将string转换为其他类型,反之不然。因为"string"有限制。
Int64String int64 json:",string" // “Int64String”:“0”
“string” opt的使用可以在Marshal/Unmarshal时自动进行数据类型的转换,减少了手动数据转换的麻烦,但是一定要注意使用的范围,对不满足的类型使用,是会报错的。
猜下对string使用"string" opt的结果会是如何呢?
Int64String string json:",string"
我们在了解源码后解答。
二、源码角度的设计处理过程
一切的使用方式肯定在设计时就已限定,我们现在看看源码中的处理过程。
在看实现的过程中,可以思考下使用的方式对不对,还有要注意的地方吗?
对某些地方非常好的实现思路,我们也可以借鉴下,对以后的编程学习大有裨益。
此处为了简洁,具体调用过程略过不讲,直接查看核心代码部分,有兴趣的话,可以查看下完整过程。
1.typeFields
在typeFields中详细的对上面提到的各种用法的tag做了处理,处理后的数据存入fileds,最后在进行编码。
2.encode
以下以int类型intEncoder为例:
对于数字类型,如果带有**“string”**则在写入正式值前后添加引号。
对于字符串类型,如果带有**“string”**,原string值再编码时会添加引号,再对结果添加引号,则格式异常,因此需要先对原值进行编码。
在了解完源码的处理过程后,我们对之前提到的问题做个解答。对string类型的字段添加"string" opt,得到的是:
Int64String string json:",string" // “Int64String”: "“1234"”
三、总结
本文主要从源码的角度说明struct json tag的为什么这么使用,以及使用时需要注意的地方。最后重复下重要的几点:
- 字段必须可导出,tag才有意义
- 忽略必须使用json:"-",不得带有opts,否则key将会变成"-"
- "string" opt仅适用于字符串、浮点、整数及布尔类型,意思是可以将这些类型的数据Marshal为string类型,或者将string类型的数据Unmarshal为这些类型。
请勿滥用,尤其是对已经是string类型的数据使用。