Golang JSON的进阶用法实例讲解
作者:yulibaozi 发布时间:2024-02-20 00:24:00
痛点
json 是当前最常用的数据传输格式之一,纯文本,容易使用,方便阅读,在通信过程中大量被使用。
你是否遇到过json中某个字段填入某种类型都适合而陷入两难境地? (例如:定义了一个port字段,你却不知道是填入 8080 ,还是 “8080” 的尴尬局面)
你是否遇到过json反解析报错是因为填入字段的类型不匹配导致的?例如:
json: cannot unmarshal number into Go struct field Host.port of type string
你是否有json某字段兼容2种或者多种的数据结构的需求?
你是否想让程序更优雅,更具有适配性,而不在被这些小细节头痛?
如果你有或者你想,获取你可以看看这篇文章。
重现问题
我们给了用户一个json如下:
{
"name":"yulibaozi",
"port":8080
}
但是,业务方却误填了”8080”,结果我们程序反解析报错,导致业务失败。
json: cannot unmarshal number into Go struct field Host.port of type string
或许你认为这是业务方的问题,但我认为我们可以更优雅的解决这个问题。
如何解决问题
我们先定义了一个结构体
type Host struct {
Name string `json:"name"`
Port Port `json:"port"`
}
心细的你会发现,Port既不是int也不是string类型,而是Port类型,而Port类型是:
type Type int
const (
Int Type = iota
String
)
type Port struct {
Type Type
IntVal int
StrVal string
}
在Port结构体中,我们发现了Type类型, 而Type类型包括了int,string两种类型。接下来就非常重要了,我们需要实现以下这两个接口。
json.Unmarshaller interface
json.Marshaller interface
实现代码如下:
type Port struct {
Type Type
IntVal int
StrVal string
}
// 实现 json.Unmarshaller 接口
func (port *Port) UnmarshalJSON(value []byte) error {
if value[0] == '"' {
port.Type = String
return json.Unmarshal(value, &port.StrVal)
}
port.Type = Int
return json.Unmarshal(value, &port.IntVal)
}
// 实现 json.Marshaller 接口
func (port Port) MarshalJSON() ([]byte, error) {
switch port.Type {
case Int:
return json.Marshal(port.IntVal)
case String:
return json.Marshal(port.StrVal)
default:
return []byte{}, fmt.Errorf("impossible Port.Type")
}
}
接下来测试:
测试反解析
测试反解析int
给出json数据:
{"name":"yulibaozi","port":8090}
反解析得到的结构体数据如下:
&{Name:yulibaozi Port:{Type:0 IntVal:8090 StrVal:}}
测试反解析string:
给出json数据:
{"name":"yulibaozi","port":"8090"}
反解析得到的结构体数据如下:
&{Name:yulibaozi Port:{Type:1 IntVal:0 StrVal:8090}}
测试编码的json
测试编码int的结构体如下:
host := &Host{
Name: "yulibaozi",
Port: Port{
Type: Int,
IntVal: 8080,
},
}
编码后的json如下:
{"name":"yulibaozi","port":8080}
测试编码string的结构体如下:
host := &Host{
Name: "yulibaozi",
Port: Port{
Type: String,
StrVal: "8080",
},
}
编码后的json数据如下:
{"name":"yulibaozi","port":"8080"}
在反编码测试中,你会发现当json填入的类型不同时,会编码到结构体中对应的字段中。
在编码测试中, 具体编码那个数据是由Type来确定的。
总结
其实,这篇文章只是分享了下json中使用的小技巧,他打破了在使用json时,需要呆板的数据结构的印象,转而走向了多变,灵活跳脱的风格,其实,这这个小tips的核心在于实现Unmarshaller,Marshaller这两个结构体,他们的实现是这个分享的关键,当然,你可以实现如开篇所说的那样,json某字段兼容2种及以上结构,当然,你也可以对yaml,toml等进行折腾,都会得到你想要的答案。
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。
来源:https://mp.weixin.qq.com/s/ZyyOD4mMML5Im09tEQss0g


猜你喜欢
- 我们通常说的双机热备是指两台机器都在运行,但并不是两台机器都同时在提供服务。当提供服务的一台出现故障的时候,另外一台会马上自动接管并且提供服
- <!doctype html> <html> <head> <meta charset="
- 将有安全问题的SQL过程删除.比较全面.一切为了安全!删除了调用shell,注册表,COM组件的破坏权限MS SQL SERVER2000使
- 本文实例讲述了codeigniter发送邮件并打印调试信息的方法。分享给大家供大家参考。具体如下:这里的codeigniter代码实现发送邮
- 代码class Shuxing(): def __init__(self, size = 10): s
- 1、下载安装 python https://www.python.org/downloads/windows/web-based insta
- 1. 真值测试所谓真值测试,是指当一种类型对象出现在if或者while条件语句中时,对象值表现为True或者False。弄清楚各种情况下的真
- 我们都知道Jupyter notebook更换主题后看着会很舒服,但是有个问题主题更换后工具栏不显示了。usename$ jt -lAvai
- 发现问题最近在工作中遇到一个问题,后端写好,前端写好,postman测试做好,一切都没有问题,但是实际用axios来实现登陆功能的时候问题就
- Socket是网络编程的一个抽象概念。通常我们用一个Socket表示“打开了一个网络链接”,而打开一个Socket需要知道目标计算机的IP地
- 我们网站的静态资源(css、js和背景图片)和web应用程序是分开部署的,几乎所有的静态资源都部署在同一个应用下。最开始的网站
- 用python连接Oracle是总是乱码,最有可能的是oracle客户端的字符编码设置不对。本人是在进行数据插入的时候总是报关键字"
- 本文介绍,在 VSCode 使用 IPython Kernel的设置方法,详细介绍如下所示:要达到的效果:只需按下 Ctrl+;,选中的几行
- 我就废话不多说了,大家还是直接看代码吧~import numpy as np kernel = np.array([1, 1, 1, 2])
- 本文实例为大家分享了pygame实现贪吃蛇游戏的具体代码,供大家参考,具体内容如下为了简化起见,游戏素材暂定为两张简单的图片(文中用的是30
- Python下实现定时任务的方式有很多种方式。下面介绍几种循环sleep:这是一种最简单的方式,在循环里放入要执行的任务,然后sleep一段
- 有时,为了方便看数据的变化情况,需要画一个动态图来看整体的变化情况。主要就是用Matplotlib库。首先,说明plot函数的说明。plt.
- 列表推导与生成器表达式当我们创建了一个列表的时候,就创建了一个可以迭代的对象:>>> squares=[n*n for n
- 背景开发项目时应学会站在巨人的肩膀上,即有效利用开发组件进行或工具提升自己的研发效率对于较简单的单体函数而言,只需要依赖原生的SDK即可完成
- 这篇文章主要是想说,“引用只能指向具体对象而不能指向引用”//创建变量testArray 并引用数组 ["1&