Golang实验性JSON API新探索
Golang实验性JSON API新探索 今天博客文章的链接:
A new experimental Go API for JSON - The Go Programming Language
Go 1.25 引入了对 encoding/json/jsontext 和 encoding/json/v2 包的实验性支持。
作为一个每天每时每刻都与 JSON 打交道的人,这对我来说真的很有趣。我个人并不关心诸如拒绝无效 UTF-8 字符之类的事情,但我能看到新的 jsontext 包的用例:
jsontext包提供了在语法层面与 JSON 交互的功能,其名称来源于 RFC 8259, section 2,其中 JSON 数据的语法字面意思就叫JSON-text。由于它只在语法层面与 JSON 交互,因此不依赖于 Go 反射。
开箱即用,反序列化性能得到了极大提升:
v2的Marshal性能大致与v1持平。有时稍快一些,有时稍慢一些。v2的Unmarshal性能则显著快于v1,基准测试显示性能提升高达 10 倍。
如果你实现一个新的接口,还可以启用流式处理:
为了获得更大的性能提升,现有的
Marshaler和Unmarshaler实现应该迁移到同时实现MarshalerTo和UnmarshalerFrom,以便它们能够受益于以纯流式方式处理 JSON。例如,在 Kubernetes 的某个特定服务中,UnmarshalJSON方法中对 OpenAPI 规范的递归解析严重影响了性能(参见 kubernetes/kube-openapi#315),而切换到UnmarshalJSONFrom则使性能提高了几个数量级。
我很有兴趣尝试一下,并希望它能早点出现。我即将启动一个项目,为现有的类似 MongoDB 的数据库 API 构建 Go 库,这听起来很适合我的项目。你们怎么看?
更多关于Golang实验性JSON API新探索的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于Golang实验性JSON API新探索的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
encoding/json/v2 确实带来了显著的性能改进,特别是在反序列化方面。以下是几个关键点的示例代码:
- 基本使用:
package main
import (
"encoding/json/v2"
"fmt"
)
type User struct {
Name string `json:"name"`
Age int `json:"age"`
Email string `json:"email"`
}
func main() {
// 序列化
user := User{Name: "Alice", Age: 30, Email: "alice@example.com"}
data, _ := v2.Marshal(user)
fmt.Println(string(data))
// 反序列化
jsonStr := `{"name":"Bob","age":25,"email":"bob@example.com"}`
var user2 User
v2.Unmarshal([]byte(jsonStr), &user2)
fmt.Printf("%+v\n", user2)
}
- 流式处理接口实现:
type CustomData struct {
Value string
}
// 实现 MarshalerTo 接口
func (c CustomData) MarshalJSONTo(enc *v2.Encoder) error {
return enc.WriteToken(v2.String(c.Value))
}
// 实现 UnmarshalerFrom 接口
func (c *CustomData) UnmarshalJSONFrom(dec *v2.Decoder) error {
token, err := dec.ReadToken()
if err != nil {
return err
}
if str, ok := token.(v2.String); ok {
c.Value = string(str)
}
return nil
}
func main() {
data := CustomData{Value: "streaming example"}
// 使用流式编码
enc := v2.NewEncoder(io.Discard)
data.MarshalJSONTo(enc)
// 使用流式解码
jsonStr := `"streaming example"`
dec := v2.NewDecoder(strings.NewReader(jsonStr))
var result CustomData
result.UnmarshalJSONFrom(dec)
}
- jsontext 包的使用:
import "encoding/json/jsontext"
func main() {
// 语法层面的 JSON 操作
jsonStr := `{"name": "test", "value": 42}`
// 验证 JSON 语法
if jsontext.Valid([]byte(jsonStr)) {
fmt.Println("Valid JSON")
}
// 直接操作 JSON 令牌
dec := jsontext.NewDecoder(strings.NewReader(jsonStr))
for {
token, err := dec.ReadToken()
if err != nil {
break
}
fmt.Printf("Token: %v\n", token)
}
}
- 性能对比示例:
func benchmarkUnmarshal(b *testing.B) {
jsonData := []byte(`{"name":"test","items":[1,2,3,4,5]}`)
b.Run("v1", func(b *testing.B) {
for i := 0; i < b.N; i++ {
var data map[string]interface{}
json.Unmarshal(jsonData, &data)
}
})
b.Run("v2", func(b *testing.B) {
for i := 0; i < b.N; i++ {
var data map[string]interface{}
v2.Unmarshal(jsonData, &data)
}
})
}
对于数据库 API 库项目,v2 包的流式处理能力特别适合处理大型 JSON 文档。新的接口设计减少了内存分配,对于高频 JSON 处理场景能提供更好的性能表现。

