golang标准兼容API的JSON处理插件库jzon的使用

golang标准兼容API的JSON处理插件库jzon的使用

jzon是一个高性能的Golang JSON库,提供了与标准库兼容的API接口。

为什么选择jzon而不是jsoniter?

jzon与jsoniter类似,但有以下改进:

  • 迭代器方法只接受确切类型(如ReadString只接受字符串,不接受null)
  • 行为几乎与标准库相同
  • 迭代器错误直接返回而不是保存在迭代器中
  • 解码器/编码器接口有额外选项,如结构体标签选项

标准库兼容性

jzon尝试实现与标准库完全兼容的版本,但有以下主要不兼容点:

  • json.Marshalerencoding.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兼容性。

主要特性

  1. API兼容标准库:可以无缝替换标准库encoding/json
  2. 高性能:比标准库快2-5倍
  3. 低内存消耗:优化内存分配策略
  4. 支持流式处理:适合处理大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))
}

性能建议

  1. 对于大量重复使用的解码器/编码器,考虑复用而不是每次都创建新的
  2. 对于大JSON数据,使用流式处理减少内存占用
  3. 如果不需要格式化输出,避免使用MarshalIndent

jzon通过优化内存分配和解析算法提供了比标准库更好的性能,特别是在处理大量JSON数据时优势更加明显。

回到顶部