golang标准兼容API的JSON处理插件库jzon的使用
golang标准兼容API的JSON处理插件库jzon的使用
jzon是一个高性能的Golang JSON库,提供了与标准库兼容的API接口。
为什么选择jzon而不是jsoniter?
jzon与jsoniter类似,但有以下改进:
- 迭代器方法只接受确切类型(如ReadString只接受字符串,不接受null)
- 行为几乎与标准库相同
- 迭代器错误直接返回而不是保存在迭代器中
- 解码器/编码器接口有额外选项,如结构体标签选项
标准库兼容性
jzon尝试实现与标准库完全兼容的版本,但有以下主要不兼容点:
json.Marshaler
和encoding.TextMarshaler
接口的指针接收器方法可能被不可寻址的值调用
使用方法
1. 标准库风格用法
import "github.com/zerosnake0/jzon"
// Unmarshal
err := jzon.Unmarshal(b, &data)
// Marshal
b, err := jzon.Marshal(&data)
// Decoder
dec := jzon.NewDecoder(reader)
defer dec.Release()
err := dec.Decode(&data)
// Encoder
enc := jzon.NewEncoder(writer)
defer enc.Release()
err := enc.Encode(&data)
2. 迭代器用法
iter := jzon.NewIterator()
defer iter.Release()
iter.Reset(b)
jzon.ReadVal(&data)
3. 流式处理
var w io.Writer
streamer := jzon.NewStreamer()
defer streamer.Release()
streamer.Reset(w)
streamer.Value(&data)
streamer.Flush()
4. 自定义解码器
type testIntDecoder struct{}
func (*testIntDecoder) Decode(ptr unsafe.Pointer, it *Iterator, opts *DecOpts) error {
// 自定义解码逻辑
}
dec := NewDecoderConfig(&DecoderOption{
ValDecoders: map[reflect.Type]ValDecoder{
reflect.TypeOf(int(0)): (*testIntDecoder)(nil),
},
CaseSensitive: true,
})
// 标准库风格
err := dec.Unmarshal(b, &data)
// 迭代器
iter := dec.NewIterator()
defer iter.Release()
5. 自定义编码器
type testIntEncoder struct{}
func (*testIntEncoder) IsEmpty(ptr unsafe.Pointer) bool {
// 检查是否为空
}
func (*testIntEncoder) Encode(ptr unsafe.Pointer, s *Streamer, opts *EncOpts) {
// 自定义编码逻辑
}
enc := NewEncoderConfig(&EncoderOption{
ValEncoders: map[reflect.Type]ValEncoder{
reflect.TypeOf(int(0)): (*testIntEncoder)(nil),
},
})
// 标准库风格
b, err := enc.Marshal(&data)
// 流式处理
streamer := enc.NewStreamer()
defer streamer.Release()
完整示例
package main
import (
"fmt"
"github.com/zerosnake0/jzon"
)
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
func main() {
// 1. Marshal示例
p := Person{Name: "Alice", Age: 25}
b, err := jzon.Marshal(&p)
if err != nil {
panic(err)
}
fmt.Println(string(b)) // 输出: {"name":"Alice","age":25}
// 2. Unmarshal示例
var p2 Person
err = jzon.Unmarshal(b, &p2)
if err != nil {
panic(err)
}
fmt.Printf("%+v\n", p2) // 输出: {Name:Alice Age:25}
// 3. 流式编码示例
streamer := jzon.NewStreamer()
defer streamer.Release()
streamer.Reset(os.Stdout)
streamer.Value(&p)
streamer.Flush() // 输出到标准输出: {"name":"Alice","age":25}
}
jzon提供了高性能且与标准库兼容的JSON处理能力,特别适合需要高性能JSON处理的场景。
更多关于golang标准兼容API的JSON处理插件库jzon的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang标准兼容API的JSON处理插件库jzon的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
jzon - Go语言高性能JSON处理库
jzon是一个兼容Go标准库API的高性能JSON处理库,它提供了比标准库encoding/json
更快的JSON编解码能力,同时保持了API兼容性。
主要特性
- API兼容标准库:可以无缝替换标准库
encoding/json
- 高性能:比标准库快2-5倍
- 低内存消耗:优化内存分配策略
- 支持流式处理:适合处理大JSON数据
安装
go get github.com/zerosnake0/jzon
基本使用
编码(序列化)
package main
import (
"fmt"
"github.com/zerosnake0/jzon"
)
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
func main() {
p := Person{Name: "Alice", Age: 25}
// 编码为JSON
data, err := jzon.Marshal(p)
if err != nil {
panic(err)
}
fmt.Println(string(data)) // 输出: {"name":"Alice","age":25}
// 带缩进的格式化输出
data, err = jzon.MarshalIndent(p, "", " ")
if err != nil {
panic(err)
}
fmt.Println(string(data))
/*
输出:
{
"name": "Alice",
"age": 25
}
*/
}
解码(反序列化)
package main
import (
"fmt"
"github.com/zerosnake0/jzon"
)
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
func main() {
jsonStr := `{"name":"Bob","age":30}`
var p Person
err := jzon.Unmarshal([]byte(jsonStr), &p)
if err != nil {
panic(err)
}
fmt.Printf("%+v\n", p) // 输出: {Name:Bob Age:30}
}
高级用法
流式编码器
package main
import (
"bytes"
"fmt"
"github.com/zerosnake0/jzon"
)
func main() {
buf := new(bytes.Buffer)
enc := jzon.NewEncoder(buf)
// 设置缩进
enc.SetIndent("", " ")
// 编码多个值
if err := enc.Encode(map[string]string{"a": "1"}); err != nil {
panic(err)
}
if err := enc.Encode(map[string]string{"b": "2"}); err != nil {
panic(err)
}
fmt.Println(buf.String())
/*
输出:
{
"a": "1"
}
{
"b": "2"
}
*/
}
流式解码器
package main
import (
"bytes"
"fmt"
"github.com/zerosnake0/jzon"
)
func main() {
jsonStr := `{"name":"Charlie","age":40}{"name":"Dave","age":50}`
dec := jzon.NewDecoder(bytes.NewBufferString(jsonStr))
for {
var p struct {
Name string `json:"name"`
Age int `json:"age"`
}
if err := dec.Decode(&p); err != nil {
break // 到达结尾
}
fmt.Printf("%+v\n", p)
}
/*
输出:
{Name:Charlie Age:40}
{Name:Dave Age:50}
*/
}
自定义编解码
package main
import (
"fmt"
"github.com/zerosnake0/jzon"
"time"
)
type CustomTime time.Time
func (ct *CustomTime) UnmarshalJSON(data []byte) error {
t, err := time.Parse(`"2006-01-02"`, string(data))
if err != nil {
return err
}
*ct = CustomTime(t)
return nil
}
func (ct CustomTime) MarshalJSON() ([]byte, error) {
return []byte(time.Time(ct).Format(`"2006-01-02"`)), nil
}
func main() {
type Event struct {
Name string `json:"name"`
Date CustomTime `json:"date"`
}
// 解码
jsonStr := `{"name":"Conference","date":"2023-05-15"}`
var e Event
if err := jzon.Unmarshal([]byte(jsonStr), &e); err != nil {
panic(err)
}
fmt.Printf("%+v\n", e)
// 编码
e.Date = CustomTime(time.Date(2023, 6, 20, 0, 0, 0, 0, time.UTC))
data, err := jzon.Marshal(e)
if err != nil {
panic(err)
}
fmt.Println(string(data))
}
性能建议
- 对于大量重复使用的解码器/编码器,考虑复用而不是每次都创建新的
- 对于大JSON数据,使用流式处理减少内存占用
- 如果不需要格式化输出,避免使用
MarshalIndent
jzon通过优化内存分配和解析算法提供了比标准库更好的性能,特别是在处理大量JSON数据时优势更加明显。