golang高性能JSON编码器插件库jettison的使用
Golang高性能JSON编码器插件库jettison的使用
Jettison简介
Jettison是一个快速灵活的Go语言JSON编码器,灵感来源于bet365/jingo,具有更丰富的功能集,旨在100%兼容标准库。
安装
Jettison使用Go模块。您可以使用以下命令获取最新版本:
go get github.com/wI2L/jettison@latest
⚠️ 从v0.7.4版本开始,该包需要Go 1.17+才能构建。
主要特性
- 快速(参见基准测试)
- 在热路径中没有动态内存分配
- 默认行为与标准库相同
- 不需要代码生成
- 清晰简洁的API
- 可配置的功能选项
- 原生支持许多标准库类型
- 自定义
AppendMarshaler
接口以避免分配 - 广泛的测试套件,将其输出与
encoding/json
进行比较
基本使用
与encoding/json
包类似,您只需将json.Marshal
函数替换为jettison.Marshal
,就能获得相同的输出但性能更好。
type X struct {
A string `json:"a"`
B int64 `json:"b"`
}
b, err := jettison.Marshal(X{
A: "Loreum",
B: 42,
})
if err != nil {
log.Fatal(err)
}
os.Stdout.Write(b)
结果
{"a":"Loreum","b":42}
高级使用
如果需要更多控制编码行为,可以使用MarshalOpts
函数。第二个参数是可变参数,接受一系列功能选项:
名称 | 描述 |
---|---|
TimeLayout |
定义用于编码time.Time 值的布局 |
DurationFormat |
定义用于编码time.Duration 值的格式 |
UnixTime |
将time.Time 值编码为表示Unix时间戳的JSON数字 |
UnsortedMap |
禁用map键排序 |
ByteArrayAsString |
将字节数组编码为JSON字符串而非JSON数组 |
RawByteSlice |
禁用用于字节切片的默认base64编码 |
NilMapEmpty |
将nil Go map编码为空JSON对象而非null |
NilSliceEmpty |
将nil Go切片编码为空JSON数组而非null |
NoStringEscaping |
禁用字符串转义 |
NoHTMLEscaping |
禁用特殊HTML字符的转义 |
NoUTF8Coercion |
禁用用Unicode替换符替换无效字节 |
AllowList |
设置白名单,表示在编组Go结构时要编码哪些字段 |
DenyList |
设置黑名单,表示在编组Go结构时要忽略哪些字段 |
NoCompact |
禁用由MarshalJSON 方法和json.RawMessage 值产生的JSON输出的压缩 |
NoNumberValidation |
禁用json.Number 值的验证 |
WithContext |
设置要传递给AppendJSONContext 方法调用的context.Context |
完整示例
package main
import (
"fmt"
"log"
"time"
"github.com/wI2L/jettison"
)
type User struct {
Name string `json:"name"`
Age int `json:"age"`
CreatedAt time.Time `json:"created_at"`
Roles []string `json:"roles,omitempty"`
Settings *Settings `json:"settings,omitnil"`
}
type Settings struct {
DarkMode bool `json:"dark_mode"`
}
func main() {
user := User{
Name: "Alice",
Age: 30,
CreatedAt: time.Now(),
Settings: nil, // 使用omitnil标签将被忽略
}
// 基本用法
jsonData, err := jettison.Marshal(user)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(jsonData))
// 高级用法 - 自定义时间格式和禁用HTML转义
jsonData, err = jettison.MarshalOpts(user,
jettison.TimeLayout(time.RFC3339),
jettison.NoHTMLEscaping(),
)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(jsonData))
}
基准测试
Jettison在性能上优于标准库和其他流行的JSON编码器。以下是简单测试结果的比较:
对于复杂数据结构,Jettison同样表现出色:
总结
Jettison是一个高性能的JSON编码器,它提供了与标准库encoding/json
相似的API,但具有更好的性能和更多的功能选项。对于需要高性能JSON编码的Go应用程序,Jettison是一个很好的选择。
更多关于golang高性能JSON编码器插件库jettison的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang高性能JSON编码器插件库jettison的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
jettison - Go高性能JSON编码器插件库
jettison是一个高性能的Go语言JSON编码器插件库,它通过实现Marshaler
和Unmarshaler
接口来提供比标准库更快的JSON处理性能。
主要特性
- 比标准库
encoding/json
更快 - 零内存分配(在某些情况下)
- 支持标准库的所有功能
- 完全兼容标准库API
安装
go get github.com/wI2L/jettison
基本使用
编码示例
package main
import (
"fmt"
"log"
"github.com/wI2L/jettison"
)
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
Address string `json:"address,omitempty"`
}
func main() {
p := Person{
Name: "Alice",
Age: 30,
Address: "123 Main St",
}
// 使用jettison进行JSON编码
jsonData, err := jettison.Marshal(p)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(jsonData))
// 输出: {"name":"Alice","age":30,"address":"123 Main St"}
}
解码示例
func main() {
jsonStr := `{"name":"Bob","age":25}`
var p Person
err := jettison.Unmarshal([]byte(jsonStr), &p)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%+v\n", p)
// 输出: {Name:Bob Age:25 Address:}
}
性能优化技巧
1. 预分配缓冲区
func main() {
p := Person{
Name: "Charlie",
Age: 40,
}
// 预分配足够大的缓冲区
buf := make([]byte, 0, 256)
// 使用jettison的Append函数避免额外分配
buf, err := jettison.Append(buf, p, jettison.NoUTF8Coercion())
if err != nil {
log.Fatal(err)
}
fmt.Println(string(buf))
}
2. 使用流式编码
func main() {
p := Person{
Name: "David",
Age: 35,
}
// 直接写入io.Writer,避免内存分配
err := jettison.NewEncoder(os.Stdout).Encode(p)
if err != nil {
log.Fatal(err)
}
}
3. 自定义编码行为
type CustomPerson struct {
Name string `json:"name"`
BirthDate time.Time `json:"birth_date"`
}
func main() {
cp := CustomPerson{
Name: "Eve",
BirthDate: time.Now(),
}
// 自定义编码选项
jsonData, err := jettison.MarshalOpts(cp,
jettison.NoUTF8Coercion(),
jettison.UnixTime(time.RFC3339),
)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(jsonData))
}
高级功能
1. 忽略空值
type User struct {
Username string `json:"username"`
Email *string `json:"email,omitempty"`
}
func main() {
u := User{
Username: "frank",
Email: nil,
}
jsonData, err := jettison.Marshal(u)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(jsonData))
// 输出: {"username":"frank"} (email字段被忽略)
}
2. 自定义键名
type Product struct {
ID int `json:"product_id"`
Description string `json:"desc,omitempty"`
Price float64
}
func main() {
p := Product{
ID: 123,
Price: 19.99,
}
jsonData, err := jettison.Marshal(p)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(jsonData))
// 输出: {"product_id":123,"Price":19.99}
}
性能对比
jettison在大多数情况下比标准库encoding/json
快2-3倍,特别是在处理大型结构体或频繁编码/解码的场景下。以下是简单的基准测试对比:
func BenchmarkStdLibMarshal(b *testing.B) {
p := Person{Name: "Benchmark", Age: 99}
for i := 0; i < b.N; i++ {
_, _ = json.Marshal(p)
}
}
func BenchmarkJettisonMarshal(b *testing.B) {
p := Person{Name: "Benchmark", Age: 99}
for i := 0; i < b.N; i++ {
_, _ = jettison.Marshal(p)
}
}
典型结果:
BenchmarkStdLibMarshal-8 2000000 750 ns/op 208 B/op 4 allocs/op
BenchmarkJettisonMarshal-8 5000000 290 ns/op 128 B/op 1 allocs/op
注意事项
- jettison与标准库完全兼容,可以逐步替换
- 对于简单用例,性能提升可能不明显
- 在极端性能要求的场景下,可以考虑更底层的JSON库如
json-iterator/go
jettison是一个优秀的JSON处理库,特别适合需要高性能JSON处理的Go应用程序。它的API设计与标准库一致,使得迁移成本极低,同时能带来显著的性能提升。