Golang高性能JSON编解码器GoJay - 目前速度最快的实现
Golang高性能JSON编解码器GoJay - 目前速度最快的实现
francoispqt/gojay
gojay - 为Golang打造的高性能JSON编码器/解码器,配备强大的流式API
刚刚发布了高性能JSON编码器/解码器的0.9.0版本(目前速度最快)。
它提供简洁的API,通过简单接口实现对结构体、数组、切片甚至通道的编解码。同时还具备强大的流式解码功能。
与大多数编解码器采用的方法不同,我们非常欢迎来自社区的反馈意见。
诚挚欢迎反馈、代码审查和贡献。
更多关于Golang高性能JSON编解码器GoJay - 目前速度最快的实现的实战教程也可以访问 https://www.itying.com/category-94-b0.html
这看起来真的非常有趣!
你进行这个项目的动机是什么?背后的设计选择有哪些?我研究过不少 Go 语言的 JSON 解析器,但之前从未见过类似这样的实现。
更多关于Golang高性能JSON编解码器GoJay - 目前速度最快的实现的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
大家好,我来汇报下最新进展。GoJay 发展得很顺利,目前版本是 0.10.6,很快就要发布 1.0.0 版本了。它仍然是目前最快的 JSON 解码器/编码器。我还基于 GoJay 构建了一个非常快速的 JSON 日志记录器,运行速度快且效率很高!
francoispqt/onelog
onelog - 专为 Golang 设计的极简、快速、零内存分配和模块化日志记录器
我将遵循您的建议,并将其添加到README中。
对于流式处理部分我完全同意,基于这个特性我已经有了几个关于其他开源包的想法。我也会添加流式编码功能。
您说得对,我完全不反对代码生成。我的意思更多是指那些难以阅读(或几乎不可读)的生成代码,比如EasyJson或ffjson。GoJay提供了简单但非常高效的API。我们可能会编写一个生成器来为结构体、切片等生成接口实现(这应该不会太难,因为接口很小),但还不确定是否会包含在v1.0版本中。
它应该很快就能在生产环境中使用。我们计划在两周内(5月11日)发布1.0版本。当准备就绪时,我会更新这个帖子或发布新帖子!
有趣!感谢详细的回复。或许你可以把这个加到README里?比如增加一个关于背景/动机/设计选择/权衡等的章节?
我真的很喜欢流式JSON支持功能,我觉得这在其他Go JSON库中是缺失的。
我一直想研究一下新的1.10版本中的strings.Builder - 我也得花点时间看看你的实现。
关于代码生成…浏览你的库时我想到的一点是,我可以把它用于代码生成…比如我可以为一堆类型(例如从.proto文件)生成代码,让它们实现正确的GoJay接口。为超过一两个结构体编写所有GoJay接口看起来工作量很大,所以我觉得这很适合用代码生成来实现。也许之后你可以在代码库中添加一个这样的示例,看看是否有人感兴趣?
你觉得这个库距离生产环境使用还有多远?版本0.9听起来离1.0很近了哈哈,但不幸的是版本号并不是这样算的!
嗨 Mike,感谢你的回答。
这个想法是在研究其他 JSON 包时产生的。当时看到的要么是大量反射,要么是一些丑陋的静态代码生成。没有通过简单接口就能实现的方案。所以我觉得如果采用零反射的方式,既能保持高性能,又能保证可读性和易用性。
在设计方面,这是我第一次尝试开发 JSON 编码器/解码器,但之前我从事过解释器和文本解析器的工作。 对于解码部分,我的想法是采用某种即时编译解码方式,这样既能最高效地使用 io.Reader,又能只解码我们需要的内容。在开发过程中,我意识到这个设计很适合使用通道进行解码,于是尝试并实现了这个功能。 对于编码部分,采用了类似的思路,使用字符串构建器并实现零反射。编码器实际上相当简单,借鉴了 Go 1.10 的 strings.Builder 来构建字节缓冲区。我相信编码器还有改进空间(比解码器的改进空间更大),我会继续完善它。
GoJay确实是一个出色的高性能JSON编解码库,它在处理JSON数据时表现优异,特别是在需要低延迟和高吞吐量的场景下。以下是一个简单的示例,展示如何使用GoJay进行结构体的编码和解码。
首先,确保你已经安装了GoJay:
go get github.com/francoispqt/gojay
示例:结构体的编码和解码
假设我们有一个简单的结构体:
package main
import (
"fmt"
"github.com/francoispqt/gojay"
)
// 定义一个结构体并实现GoJay的接口
type User struct {
ID int `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
}
// 实现gojay.MarshalerJSONObject接口
func (u *User) MarshalJSONObject(enc *gojay.Encoder) {
enc.IntKey("id", u.ID)
enc.StringKey("name", u.Name)
enc.StringKey("email", u.Email)
}
func (u *User) IsNil() bool {
return u == nil
}
// 实现gojay.UnmarshalerJSONObject接口
func (u *User) UnmarshalJSONObject(dec *gojay.Decoder, key string) error {
switch key {
case "id":
return dec.Int(&u.ID)
case "name":
return dec.String(&u.Name)
case "email":
return dec.String(&u.Email)
}
return nil
}
func (u *User) NKeys() int {
return 3
}
func main() {
// 编码示例
user := &User{ID: 1, Name: "Alice", Email: "alice@example.com"}
encoded, err := gojay.MarshalJSONObject(user)
if err != nil {
panic(err)
}
fmt.Println("Encoded JSON:", string(encoded))
// 解码示例
jsonStr := `{"id":2,"name":"Bob","email":"bob@example.com"}`
decodedUser := &User{}
err = gojay.UnmarshalJSONObject([]byte(jsonStr), decodedUser)
if err != nil {
panic(err)
}
fmt.Printf("Decoded User: ID=%d, Name=%s, Email=%s\n", decodedUser.ID, decodedUser.Name, decodedUser.Email)
}
流式解码示例
GoJay还支持流式解码,这对于处理大型JSON数据或网络流非常有用。以下是一个简单的流式解码示例:
package main
import (
"fmt"
"strings"
"github.com/francoispqt/gojay"
)
// 定义一个流式解码器处理数组
func main() {
jsonStream := `[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}]`
decoder := gojay.NewDecoder(strings.NewReader(jsonStream))
// 开始数组解码
err := decoder.DecodeArray(func(dec *gojay.Decoder) error {
user := &User{}
if err := dec.Object(user); err != nil {
return err
}
fmt.Printf("Streamed User: ID=%d, Name=%s\n", user.ID, user.Name)
return nil
})
if err != nil {
panic(err)
}
}
这些示例展示了GoJay在编码、解码和流式处理方面的基本用法。它的API设计简洁,性能优越,适合需要高效JSON处理的Go应用。如果你有更复杂的用例,可以进一步探索其文档和API。

