背景
最近在做一个数据处理的项目,需要解析大量的 JSON 数据。用 Go 标准库的 encoding/json 感觉性能不太够,就找了几个第三方库测试一下。
其中有个叫 FxJSON 的库,宣传说性能比标准库快很多倍。本来觉得可能是夸大宣传,但测试下来发现确实还不错,于是就果断点了Star
安装:
go get github.com/icloudza/fxjson
简单测试
写了个简单的测试程序:
package main
import (
"encoding/json"
"fmt"
"time"
"github.com/icloudza/fxjson"
)
func main() {
jsonData := `{
"users": [
{"name": "张三", "age": 25, "active": true},
{"name": "李四", "age": 30, "active": false},
{"name": "王五", "age": 28, "active": true}
]
}`
iterations := 10000
// 标准库测试
start := time.Now()
for i := 0; i < iterations; i++ {
var data map[string]interface{}
json.Unmarshal([]byte(jsonData), &data)
users := data["users"].([]interface{})
for _, user := range users {
u := user.(map[string]interface{})
_ = u["name"].(string)
_ = int(u["age"].(float64))
_ = u["active"].(bool)
}
}
stdTime := time.Since(start)
// FxJSON 测试
start = time.Now()
for i := 0; i < iterations; i++ {
node := fxjson.FromString(jsonData)
node.Get("users").ArrayForEach(func(index int, user fxjson.Node) bool {
_ = user.Get("name").StringOr("")
_ = user.Get("age").IntOr(0)
_ = user.Get("active").BoolOr(false)
return true
})
}
fxTime := time.Since(start)
fmt.Printf("标准库: %v\n", stdTime)
fmt.Printf("FxJSON: %v\n", fxTime)
fmt.Printf("提升: %.1f倍\n", float64(stdTime)/float64(fxTime))
}
测试结果:
标准库: 89.2ms
FxJSON: 4.1ms
提升: 21.8倍
在这个场景下确实快了不少。
基本用法
API 设计比较直观:
// 解析 JSON
node := fxjson.FromString(jsonStr)
// 或者
node := fxjson.FromBytes(jsonBytes)
// 获取值,带默认值
name := node.Get("name").StringOr("默认名称")
age := node.Get("age").IntOr(0)
active := node.Get("active").BoolOr(false)
// 路径访问
email := node.GetPath("user.profile.email").StringOr("")
// 数组遍历
node.Get("items").ArrayForEach(func(index int, item fxjson.Node) bool {
fmt.Printf("第%d项: %s\n", index, item.Get("name").StringOr(""))
return true // 返回false可以终止遍历
})
实际使用
在项目中试用了一下:
配置文件读取
configBytes, _ := os.ReadFile("config.json")
config := fxjson.FromBytes(configBytes)
dbHost := config.GetPath("database.host").StringOr("localhost")
dbPort := config.GetPath("database.port").IntOr(3306)
redisEnabled := config.GetPath("redis.enabled").BoolOr(false)
比起定义结构体然后 json.Unmarshal,这种方式更灵活一些。
API 响应处理
resp, _ := http.Get("https://api.example.com/users")
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
data := fxjson.FromBytes(body)
total := data.GetPath("meta.total").IntOr(0)
var userNames []string
data.Get("data").ArrayForEach(func(i int, user fxjson.Node) bool {
if user.Get("status").StringOr("") == "active" {
userNames = append(userNames, user.Get("name").StringOr(""))
}
return true
})
性能特点
从文档看,主要的性能优化点:
- 减少内存分配。标准库需要创建很多 interface{} 和 map,FxJSON 直接在原始数据上操作
- 有缓存机制。重复访问相同路径时会更快
- 数组遍历做了优化
官方给的 benchmark 数据比较夸张,实际使用中提升程度取决于具体场景。处理大量数据时确实有明显改善。
一些注意点
- 错误处理方式不同。标准库会返回 error,这个库用默认值的方式处理
- 如果需要严格的类型检查,可能还是标准库更合适
- 对于简单场景,可能感受不到太大差别
总结
如果项目中有大量 JSON 处理,特别是性能敏感的场景,这个库值得试试。API 用起来比较方便,性能也确实有提升。
当然,选择什么库还是要根据具体需求。如果对性能要求不高,标准库其实也够用。