Golang 在序列化和反序列化一个 Struct 时,如果指定了 JSON tag 会严格按照指定的 tag 内容来执行,在没有指定 tag 或 tag 大小写不精准时,会有一些默认规则。
序列化
序列化的情况比较简单:
- 指定了 tag 的可导出字段,按照 tag 的命名进行序列化
- 没有指定 tag 的但可以导出的字段(首字母大写)会完全按照变量命名来进行序列化
1 | type A struct { |
上边这段代码输出:
1 | {"Case":1,"Cas_E":3,"ok":4} |
casE
这个字段没有输出,原因是因为他是个不可导出的私有字段,即使设置了 tag 也不可序列化。CaSE
序列话后的 key 为ok
是因为我们给它指定了 tag- 其余字段都是按照我们原本的拼写格式进行的输出
反序列化
序列化的情况稍微有点复杂,其整体的优先级为:
- 先按 tag 匹配,后按字段名匹配
- 有 tag 的仅匹配 tag,没有tag 的可参与字段名匹配
- 先精确匹配,后模糊匹配
- 多个模糊匹配的按照声明在前的匹配
我们看几个例子:
情况1,带 tag 的两个字段都无法匹配上(精准匹配+模糊匹配),不带 tag 的两个字段都可以模糊匹配上,优先赋值给前边声明的字段:
1 | type B struct { |
情况2,带 tag 的其中一个字段可以模糊匹配上:
1 | type B struct { |
情况3,带 tag 的两个字段都可以匹配上,第一个模糊匹配,第二个精准匹配: