golang高性能JSON解析与JSONPath操作插件库OjG的使用
Golang高性能JSON解析与JSONPath操作插件库OjG的使用
OjG (Optimized JSON for Go) 是一个高性能的JSON解析器,提供多种JSON处理工具。OjG特别适合处理大型数据集,尤其是数据结构不固定的情况。
主要特性
- 快速的JSON解析器(性能优于标准库)
- 完整的JSONPath实现,支持简单类型和结构体操作
- 通用类型(虽然不是Go泛型,但提供类型安全的JSON元素)
- 快速的JSON验证器(比io.Reader快7倍)
- 带排序选项的快速JSON写入器(快4倍)
- 使用简单组装计划从JSON源构建JSON
- 使用push和pop方法的简单数据构建器
- 类似Ruby Oj的对象编码和解码方法
- 简单编码表示法(SEN),一种省略逗号和引号的懒JSON写法
使用示例
基本解析
package main
import (
"fmt"
"github.com/ohler55/ojg/oj"
)
func main() {
// 解析JSON字符串
obj, err := oj.ParseString(`{
"a":[
{"x":1,"y":2,"z":3},
{"x":2,"y":4,"z":6}
]
}`)
if err != nil {
fmt.Println("解析错误:", err)
return
}
fmt.Println("解析结果:", obj)
}
使用JSONPath表达式
package main
import (
"fmt"
"github.com/ohler55/ojg/jp"
"github.com/ohler55/ojg/oj"
)
func main() {
// 解析JSON字符串
obj, _ := oj.ParseString(`{
"a":[
{"x":1,"y":2,"z":3},
{"x":2,"y":4,"z":6}
]
}`)
// 解析JSONPath表达式
x, err := jp.ParseString("a[?(@.x > 1)].y")
if err != nil {
fmt.Println("JSONPath解析错误:", err)
return
}
// 应用JSONPath获取结果
ys := x.Get(obj)
fmt.Println("JSONPath结果:", ys) // 输出: [4]
}
命令行工具
OjG提供了一个命令行工具oj
,可以使用JSONPath进行过滤和提取JSON元素,还支持排序、重新格式化和着色选项。
$ oj -m "(@.name == 'Pete')" myfile.json
安装
go get github.com/ohler55/ojg
go get github.com/ohler55/ojg/cmd/oj
或者在Go文件中直接导入:
import (
"github.com/ohler55/ojg/alt"
"github.com/ohler55/ojg/asm"
"github.com/ohler55/ojg/gen"
"github.com/ohler55/ojg/jp"
"github.com/ohler55/ojg/oj"
"github.com/ohler55/ojg/sen"
)
要构建并安装oj
应用程序:
go install ./...
或者使用Homebrew安装:
brew install oj
性能基准
OjG在性能上显著优于标准库的JSON处理:
Parse string/[]byte
json.Unmarshal 55916 ns/op 17776 B/op 334 allocs/op
oj.Parse 39570 ns/op 18488 B/op 429 allocs/op
oj-reuse.Parse 17881 ns/op 5691 B/op 364 allocs/op
oj-reuse.Parse █████████████████████▉ 3.13
oj.Parse █████████▉ 1.41
json.Unmarshal ▓▓▓▓▓▓▓ 1.00
Parse io.Reader
json.Decode 63029 ns/op 32449 B/op 344 allocs/op
oj.ParseReader 34289 ns/op 22583 B/op 430 allocs/op
oj-reuse.ParseReader 25094 ns/op 9788 B/op 365 allocs/op
oj.TokenizeLoad 13610 ns/op 6072 B/op 157 allocs/op
oj.TokenizeLoad ████████████████████████████████▍ 4.63
oj-reuse.ParseReader █████████████████▌ 2.51
oj.ParseReader ████████████▊ 1.84
json.Decode ▓▓▓▓▓▓▓ 1.00
to JSON with indentation
json.Marshal 78762 ns/op 26978 B/op 352 allocs/op
oj.JSON 7662 ns/op 0 B/op 0 allocs/op
sen.Bytes 9053 ns/op 0 B/op 0 allocs/op
oj.JSON ███████████████████████████████████████████████████████████████████████▉ 10.28
sen.Bytes ████████████████████████████████████████████████████████████▉ 8.70
json.Marshal ▓▓▓▓▓▓▓ 1.00
更多关于golang高性能JSON解析与JSONPath操作插件库OjG的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang高性能JSON解析与JSONPath操作插件库OjG的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
使用OjG进行高性能JSON解析与JSONPath操作
OjG是Go语言中一个高性能的JSON处理库,提供了快速的JSON解析和JSONPath查询功能。下面我将详细介绍如何使用OjG进行高效的JSON操作。
安装OjG
首先安装OjG库:
go get github.com/ohler55/ojg/oj
go get github.com/ohler55/ojg/jp
基本JSON解析
快速解析JSON字符串
package main
import (
"fmt"
"github.com/ohler55/ojg/oj"
)
func main() {
jsonStr := `{"name":"John","age":30,"city":"New York"}`
// 解析JSON
obj, err := oj.ParseString(jsonStr)
if err != nil {
panic(err)
}
// 转换为map
data := obj.(map[string]interface{})
fmt.Println("Name:", data["name"])
fmt.Println("Age:", data["age"])
fmt.Println("City:", data["city"])
}
带选项的解析
func parseWithOptions() {
jsonStr := `{"name":"John","age":30,"city":"New York"}`
// 创建解析选项
opt := &oj.Options{
UseFloat: true, // 使用float64而不是默认的int
TimeFormat: "unix", // 时间格式
CreateKey: "^", // 特殊字符处理
FullTyping: true, // 保留完整类型信息
}
obj, err := oj.ParseString(jsonStr, opt)
if err != nil {
panic(err)
}
fmt.Printf("%#v\n", obj)
}
JSONPath查询
OjG提供了强大的JSONPath功能来查询JSON数据。
基本JSONPath查询
package main
import (
"fmt"
"github.com/ohler55/ojg/jp"
"github.com/ohler55/ojg/oj"
)
func main() {
jsonStr := `{
"store": {
"book": [
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
},
{
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
}
}`
// 解析JSON
obj, err := oj.ParseString(jsonStr)
if err != nil {
panic(err)
}
// 创建JSONPath表达式
x, err := jp.ParseString("$.store.book[*].author")
if err != nil {
panic(err)
}
// 执行查询
authors := x.Get(obj)
fmt.Println("Authors:", authors)
}
常用JSONPath示例
func jsonPathExamples() {
jsonStr := `{"store": {"book": [{"title": "Book1"}, {"title": "Book2"}]}}`
obj, _ := oj.ParseString(jsonStr)
// 1. 获取所有书籍标题
x1, _ := jp.ParseString("$.store.book[*].title")
titles := x1.Get(obj)
fmt.Println("Titles:", titles)
// 2. 获取第一本书
x2, _ := jp.ParseString("$.store.book[0]")
firstBook := x2.Get(obj)
fmt.Println("First book:", firstBook)
// 3. 获取最后一本书
x3, _ := jp.ParseString("$.store.book[-1]")
lastBook := x3.Get(obj)
fmt.Println("Last book:", lastBook)
// 4. 条件查询
x4, _ := jp.ParseString("$.store.book[?(@.title == 'Book2')]")
matchingBooks := x4.Get(obj)
fmt.Println("Matching books:", matchingBooks)
}
性能优化技巧
- 重用解析器:避免重复创建解析器实例
var parser = oj.Parser{Reuse: true}
func parseWithReuse(jsonStr string) {
obj, err := parser.ParseString(jsonStr)
if err != nil {
panic(err)
}
// 使用obj...
}
- 预编译JSONPath:对于频繁使用的JSONPath表达式,提前编译
var (
bookTitlesPath, _ = jp.ParseString("$.store.book[*].title")
bookPricesPath, _ = jp.ParseString("$.store.book[*].price")
)
func queryPrecompiledPaths(obj interface{}) {
titles := bookTitlesPath.Get(obj)
prices := bookPricesPath.Get(obj)
// 使用结果...
}
- 使用简单类型:在可能的情况下使用简单类型而非interface{}
type Book struct {
Title string `json:"title"`
Author string `json:"author"`
Price float64 `json:"price"`
}
type Store struct {
Books []Book `json:"book"`
}
func parseToStruct(jsonStr string) {
var data struct {
Store Store `json:"store"`
}
err := oj.Unmarshal([]byte(jsonStr), &data)
if err != nil {
panic(err)
}
// 直接访问结构体字段,类型安全且高效
for _, book := range data.Store.Books {
fmt.Println(book.Title, book.Price)
}
}
高级功能
修改JSON数据
func modifyJson() {
jsonStr := `{"name":"John","age":30}`
obj, _ := oj.ParseString(jsonStr)
// 创建修改表达式
x, _ := jp.ParseString("$.age")
// 修改age字段
x.Set(obj, 31)
// 转换为JSON字符串
modifiedJson, _ := oj.Marshal(obj)
fmt.Println(string(modifiedJson))
}
流式解析大JSON
对于大JSON文件,可以使用流式解析:
func streamParse() {
jsonStr := `{"results":[{"id":1},{"id":2},{"id":3}]}`
// 创建流解析器
callback := func(obj interface{}) bool {
fmt.Println("Got object:", obj)
return true // 返回false可以停止解析
}
err := oj.Parse([]byte(jsonStr), callback)
if err != nil {
panic(err)
}
}
性能对比
OjG在性能上通常优于标准库的encoding/json
,特别是在处理大JSON数据时:
- 解析速度通常快2-5倍
- 内存使用更高效
- JSONPath查询比手动遍历map更简洁高效
结论
OjG是Go中处理JSON的高性能选择,特别适合:
- 需要快速解析大JSON文件的场景
- 需要复杂JSON查询的场景
- 对性能有较高要求的应用
通过合理使用OjG的解析选项、JSONPath预编译和流式处理,可以显著提升JSON处理的效率。