01
介绍
在 Golang 语言中,我们一般会使用标准库 encoding/json
序列化/反序列化 JSON,但是因为 encoding/json
需要使用反射,所以如果在性能要求比较高的场景中,它就不太合适了。
本文我们要介绍的三方库 easyjson
,它提供了快速且简单的方式去序列化和反序列化 Golang 结构体 / JSON,官方文档介绍,在性能测试中,easyjson
比标准库 encoding/json
高 4~5 倍。
easyjson
的目标是保持生成的 Golang 代码足够简单,以便它可以很容易地优化或修复,并且通过提供标准库 encoding/json
中无法提供的选项,为用户提供自定义生成代码的能力,例如生成 snake_case
名称或默认启用 omitempty
行为。
02
安装和生成代码
在准备使用 easyjson
之前,我们需要先安装 easyjson
。
安装命令:
代码语言:javascript复制go get -u github.com/mailru/easyjson/...
安装成功之后,我们就可以使用 easyjson
生成代码了,也非常简单,仅需运行以下命令。
生成代码命令:
代码语言:javascript复制easyjson -all <file>.go
运行上面这条命令,会自动生成一个文件 <file>_easyjson.go
,文件中包含 <file>.go
文件中所有结构体对应的 marshaler 和 unmarshaler 方法。
需要注意的是,我们使用 easyjson
命令生成代码之前,需要设置 GOPATH 环境变量。
如果我们使用 easyjson
命令生成代码时,没有指定 -all
选项,我们需要在需要生成相应代码的结构体上方添加一个标签 //easyjson:json
。
我们使用 easyjson -all <file>.go
生成代码时,如果文件中个别结构体不需要生成相应代码,我们可以在该结构体上方添加一个标签 //easyjson:skip
。
除了 -all
选项,还有一些其他比较常用的选项,限于篇幅,我们不再赘述,感兴趣的读者朋友们可以查阅官方文档了解更多。
03
使用示例
读者朋友们阅读完以上内容后,想必一定会动手操练一把,以下是本文的示例代码,供读者朋友们做个参考,完整代码可以翻阅 GitHub。
结构体:
代码语言:javascript复制type User struct {
ID uint64 `json:"id"`
Name string `json:"name"`
}
序列化:
代码语言:javascript复制// 序列化
func encode() {
user := &model.User{
ID: 1,
Name: "lucy",
}
bs, err := user.MarshalJSON()
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("encode() type=%Tnbs=%vnstr=%sn", bs, bs, string(bs))
}
反序列化:
代码语言:javascript复制// 反序列化
func decode() {
user := new(model.User)
str := `{"id":1,"name":"lucy"}`
err := user.UnmarshalJSON([]byte(str))
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("decode() user=% vn", user)
}
04
总结
本文我们重点介绍了相比 Golang 标准库 encoding/json
性能较高的三方库 easyjson
,包括安装、使用和示例代码。感兴趣的读者朋友,可以 benchmark 做个对比。
读到这里,读者朋友们可能会有个疑问,既然 easyjson
不会使用反射,为什么结构体定义时还使用 json
标签,实际上,easyjson
在生成代码时,也使用了反射。
在应用程序开发中,如果标准库可以满足需求,不建议引入三方库,导致增加应用程序的维护成本。
推荐阅读:
Golang 语言中 map 有哪些陷阱?
Golang 语言是面向对象编程风格的编程语言吗?
Golang 语言中怎么解码 4 种常见JSON 格式数据?
Go 语言学习之基础数据类型
Golang 语言中的非类型安全指针
参考资料:
https://github.com/mailru/easyjson
https://pkg.go.dev/encoding/json@go1.16.7