golang高性能JSON编码器插件库jettison的使用

Golang高性能JSON编码器插件库jettison的使用

Jettison简介

Jettison是一个快速灵活的Go语言JSON编码器,灵感来源于bet365/jingo,具有更丰富的功能集,旨在100%兼容标准库。

GoCaptain

安装

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编码器。以下是简单测试结果的比较:

Simple Benchmark Graph

对于复杂数据结构,Jettison同样表现出色:

Complex Benchmark Graph

总结

Jettison是一个高性能的JSON编码器,它提供了与标准库encoding/json相似的API,但具有更好的性能和更多的功能选项。对于需要高性能JSON编码的Go应用程序,Jettison是一个很好的选择。


更多关于golang高性能JSON编码器插件库jettison的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang高性能JSON编码器插件库jettison的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


jettison - Go高性能JSON编码器插件库

jettison是一个高性能的Go语言JSON编码器插件库,它通过实现MarshalerUnmarshaler接口来提供比标准库更快的JSON处理性能。

主要特性

  1. 比标准库encoding/json更快
  2. 零内存分配(在某些情况下)
  3. 支持标准库的所有功能
  4. 完全兼容标准库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

注意事项

  1. jettison与标准库完全兼容,可以逐步替换
  2. 对于简单用例,性能提升可能不明显
  3. 在极端性能要求的场景下,可以考虑更底层的JSON库如json-iterator/go

jettison是一个优秀的JSON处理库,特别适合需要高性能JSON处理的Go应用程序。它的API设计与标准库一致,使得迁移成本极低,同时能带来显著的性能提升。

回到顶部