API 参考手册
FxJSON 提供了简洁而强大的 API,让您能够高效处理 JSON 数据。本文档将按照使用频率和学习难度组织,帮助您快速找到需要的方法。
快速索引
- 核心解析函数 - 如何开始使用 FxJSON
- 基础数据访问 - 获取 JSON 中的值
- 类型转换方法 - 安全地转换数据类型
- 数组操作 - 处理 JSON 数组
- 对象操作 - 处理 JSON 对象
- 高级功能 - 数据验证、序列化等高级特性
核心解析函数
这些函数是使用 FxJSON 的起点,用于将 JSON 字符串或字节数组转换为可操作的 Node 对象。
FromString()
func FromString(s string) Node最常用的解析函数,从 JSON 字符串创建 Node。
使用场景:处理配置文件、API 响应等字符串格式的 JSON
// 基本用法
jsonStr := `{"name": "张三", "age": 30}`
node := fxjson.FromString(jsonStr)
name := node.Get("name").StringOr("") // "张三"FromBytes()
func FromBytes(b []byte) Node从字节数组解析 JSON,性能略好于字符串版本。
使用场景:处理网络请求、文件读取等字节数据
// 处理 HTTP 响应
response, _ := http.Get("https://api.example.com/user")
body, _ := io.ReadAll(response.Body)
node := fxjson.FromBytes(body)FromStringWithOptions() / FromBytesWithOptions()
func FromStringWithOptions(s string, opts ParseOptions) Node
func FromBytesWithOptions(b []byte, opts ParseOptions) Node带自定义解析选项的版本,用于处理特殊需求。
使用场景:需要限制解析深度、字符串长度等安全场景
// 自定义解析选项
opts := fxjson.ParseOptions{
MaxDepth: 100, // 最大嵌套深度
MaxStringLen: 10000, // 最大字符串长度
StrictMode: true, // 严格模式
}
node := fxjson.FromStringWithOptions(jsonStr, opts)基础数据访问
Get()
func (n Node) Get(key string) Node核心访问方法,根据键名获取对象中的字段。
json := `{"user": {"name": "张三", "profile": {"city": "北京"}}}`
node := fxjson.FromString(json)
// 链式访问
name := node.Get("user").Get("name").StringOr("") // "张三"
city := node.Get("user").Get("profile").Get("city").StringOr("") // "北京"GetPath()
func (n Node) GetPath(path string) Node路径访问方法,使用点号分隔的路径字符串访问嵌套数据,比链式调用更简洁。
// 等价于上面的链式调用,但更简洁
name := node.GetPath("user.name").StringOr("") // "张三"
city := node.GetPath("user.profile.city").StringOr("") // "北京"Index()
func (n Node) Index(i int) Node根据索引访问数组元素。
json := `{"users": ["张三", "李四", "王五"]}`
node := fxjson.FromString(json)
users := node.Get("users")
first := users.Index(0).StringOr("") // "张三"
second := users.Index(1).StringOr("") // "李四"类型转换方法
FxJSON 提供两套类型转换方法:安全方法(推荐)和严格方法。
安全转换方法(推荐)
这些方法自动处理错误,提供默认值,是日常使用的首选。
StringOr()
func (n Node) StringOr(defaultValue string) string获取字符串值,失败时返回默认值。
name := node.Get("name").StringOr("未知用户")
email := node.Get("email").StringOr("未提供邮箱")IntOr()
func (n Node) IntOr(defaultValue int64) int64获取整数值,失败时返回默认值。
age := node.Get("age").IntOr(0)
score := node.Get("score").IntOr(-1)FloatOr()
func (n Node) FloatOr(defaultValue float64) float64获取浮点数值,失败时返回默认值。
price := node.Get("price").FloatOr(0.0)
rating := node.Get("rating").FloatOr(5.0)BoolOr()
func (n Node) BoolOr(defaultValue bool) bool获取布尔值,失败时返回默认值。
active := node.Get("active").BoolOr(false)
verified := node.Get("verified").BoolOr(false)UintOr()
func (n Node) UintOr(defaultValue uint64) uint64获取无符号整数值,失败时返回默认值。
count := node.Get("count").UintOr(0)
id := node.Get("id").UintOr(0)严格转换方法
这些方法返回错误,适合需要明确错误处理的场景。
String() / Int() / Float() / Bool() / Uint()
func (n Node) String() (string, error)
func (n Node) Int() (int64, error)
func (n Node) Float() (float64, error)
func (n Node) Bool() (bool, error)
func (n Node) Uint() (uint64, error)// 严格模式示例
name, err := node.Get("name").String()
if err != nil {
log.Printf("获取姓名失败: %v", err)
return
}
age, err := node.Get("age").Int()
if err != nil {
log.Printf("获取年龄失败: %v", err)
return
}
// 无符号整数
count, err := node.Get("count").Uint()
if err != nil {
log.Printf("获取计数失败: %v", err)
return
}特殊转换方法
NumStr() / FloatString()
func (n Node) NumStr() (string, error)
func (n Node) FloatString() (string, error)获取数字的字符串表示形式,保留原始格式。
json := `{"price": 99.99, "count": 42}`
node := fxjson.FromString(json)
// 获取数字的字符串表示
priceStr, _ := node.Get("price").NumStr() // "99.99"
countStr, _ := node.Get("count").NumStr() // "42"数组操作
Len()
func (n Node) Len() int获取数组或对象的长度。
json := `{"users": ["张三", "李四"], "count": 2}`
node := fxjson.FromString(json)
arrayLen := node.Get("users").Len() // 2
objectLen := node.Len() // 2(对象有2个字段)ArrayForEach()
func (n Node) ArrayForEach(fn func(index int, item Node) bool)高性能数组遍历,比标准库快 67 倍,零内存分配。
json := `{"scores": [95, 87, 92, 88]}`
node := fxjson.FromString(json)
total := int64(0)
count := 0
node.Get("scores").ArrayForEach(func(index int, item fxjson.Node) bool {
score := item.IntOr(0)
total += score
count++
fmt.Printf("第%d个分数: %d\n", index+1, score)
return true // 返回 true 继续遍历,false 停止
})
average := float64(total) / float64(count)
fmt.Printf("平均分: %.1f\n", average)ToSlice系列方法
将 JSON 数组转换为 Go 切片。
ToStringSlice()
func (n Node) ToStringSlice() ([]string, error)ToIntSlice()
func (n Node) ToIntSlice() ([]int64, error)ToFloatSlice()
func (n Node) ToFloatSlice() ([]float64, error)json := `{
"names": ["张三", "李四", "王五"],
"ages": [25, 30, 35],
"scores": [95.5, 87.0, 92.5]
}`
node := fxjson.FromString(json)
// 转换为字符串切片
names, err := node.Get("names").ToStringSlice()
if err == nil {
fmt.Printf("姓名列表: %v\n", names)
}
// 转换为整数切片
ages, err := node.Get("ages").ToIntSlice()
if err == nil {
fmt.Printf("年龄列表: %v\n", ages)
}
// 转换为浮点数切片
scores, err := node.Get("scores").ToFloatSlice()
if err == nil {
fmt.Printf("分数列表: %v\n", scores)
}对象操作
ForEach()
func (n Node) ForEach(fn func(key string, value Node) bool)高性能对象遍历,比标准库快 20 倍,零内存分配。
json := `{
"users": {
"admin": {"name": "管理员", "level": 5},
"guest": {"name": "访客", "level": 1}
}
}`
node := fxjson.FromString(json)
node.Get("users").ForEach(func(userType string, userInfo fxjson.Node) bool {
name := userInfo.Get("name").StringOr("")
level := userInfo.Get("level").IntOr(0)
fmt.Printf("%s: %s (等级 %d)\n", userType, name, level)
return true
})Keys()
func (n Node) Keys() []string获取对象的所有键名。
json := `{"name": "张三", "age": 30, "city": "北京"}`
node := fxjson.FromString(json)
keys := node.Keys()
fmt.Printf("对象的键: %v\n", keys) // ["name", "age", "city"]类型检查方法
基础类型检查
func (n Node) IsString() bool // 是否为字符串
func (n Node) IsNumber() bool // 是否为数字
func (n Node) IsBool() bool // 是否为布尔值
func (n Node) IsNull() bool // 是否为 null
func (n Node) IsArray() bool // 是否为数组
func (n Node) IsObject() bool // 是否为对象json := `{
"name": "张三",
"age": 30,
"active": true,
"address": null,
"hobbies": ["阅读"],
"profile": {"city": "北京"}
}`
node := fxjson.FromString(json)
fmt.Printf("name 是字符串: %t\n", node.Get("name").IsString()) // true
fmt.Printf("age 是数字: %t\n", node.Get("age").IsNumber()) // true
fmt.Printf("active 是布尔值: %t\n", node.Get("active").IsBool()) // true
fmt.Printf("address 是 null: %t\n", node.Get("address").IsNull()) // true
fmt.Printf("hobbies 是数组: %t\n", node.Get("hobbies").IsArray()) // true
fmt.Printf("profile 是对象: %t\n", node.Get("profile").IsObject())// true分组类型检查
func (n Node) IsScalar() bool // 是否为标量(字符串、数字、布尔值、null)
func (n Node) IsContainer() bool // 是否为容器(数组或对象)Exists()
func (n Node) Exists() bool检查字段是否存在(非常实用的方法)。
if node.Get("optional_field").Exists() {
// 字段存在时才处理
value := node.Get("optional_field").StringOr("")
fmt.Printf("可选字段的值: %s\n", value)
}原始数据访问
Raw() / RawString()
func (n Node) Raw() []byte
func (n Node) RawString() (string, error)获取节点的原始 JSON 数据。
json := `{"user": {"name": "张三", "age": 30}}`
node := fxjson.FromString(json)
// 获取原始字节
userRaw := node.Get("user").Raw()
fmt.Printf("原始数据: %s\n", userRaw) // {"name": "张三", "age": 30}
// 获取原始字符串
userStr, _ := node.Get("user").RawString()Type() / Kind()
func (n Node) Type() byte
func (n Node) Kind() NodeType获取节点的类型标识。
node := fxjson.FromString(`{"name": "张三"}`)
typ := node.Type() // 返回 'o' (对象)
kind := node.Kind() // 返回 TypeObject
switch kind {
case fxjson.TypeObject:
fmt.Println("这是一个对象")
case fxjson.TypeArray:
fmt.Println("这是一个数组")
case fxjson.TypeString:
fmt.Println("这是一个字符串")
}高级功能
数据验证
FxJSON 内置多种验证方法,方便进行数据校验。
格式验证
func (n Node) IsValidEmail() bool // 验证邮箱格式
func (n Node) IsValidURL() bool // 验证 URL 格式
func (n Node) IsValidIP() bool // 验证 IP 地址格式
func (n Node) IsValidJSON() bool // 验证 JSON 格式json := `{
"email": "user@example.com",
"website": "https://example.com",
"server": "192.168.1.1"
}`
node := fxjson.FromString(json)
email := node.Get("email")
if email.IsValidEmail() {
fmt.Printf("邮箱 %s 格式正确\n", email.StringOr(""))
}
url := node.Get("website")
if url.IsValidURL() {
fmt.Printf("网址 %s 格式正确\n", url.StringOr(""))
}
ip := node.Get("server")
if ip.IsValidIP() {
fmt.Printf("IP地址 %s 格式正确\n", ip.StringOr(""))
}数值范围验证
func (n Node) InRange(min, max float64) bool // 检查数值是否在指定范围内json := `{"age": 25, "score": 95.5}`
node := fxjson.FromString(json)
age := node.Get("age")
if age.InRange(18, 65) {
fmt.Printf("年龄 %d 在合法范围内\n", age.IntOr(0))
}
score := node.Get("score")
if score.InRange(0, 100) {
fmt.Printf("分数 %.1f 在有效范围内\n", score.FloatOr(0))
}结构体操作与序列化
序列化方法
func Marshal(v interface{}) ([]byte, error) // 标准序列化
func FastMarshal(v interface{}) []byte // 高性能序列化
func MarshalIndent(v interface{}, prefix, indent string) ([]byte, error) // 美化序列化
func MarshalWithOptions(v interface{}, opts SerializeOptions) ([]byte, error) // 带选项序列化
func MarshalToString(v interface{}) (string, error) // 序列化为字符串
func MarshalToStringWithOptions(v interface{}, opts SerializeOptions) (string, error)Node 序列化方法
func (n Node) ToJSON() (string, error) // 转为 JSON 字符串
func (n Node) ToJSONIndent(prefix, indent string) (string, error) // 美化 JSON
func (n Node) ToJSONWithOptions(opts SerializeOptions) (string, error) // 带选项转换
func (n Node) ToJSONBytes() ([]byte, error) // 转为 JSON 字节
func (n Node) ToJSONBytesWithOptions(opts SerializeOptions) ([]byte, error)
func (n Node) ToJSONFast() string // 快速转换反序列化方法
func DecodeStruct(data []byte, v interface{}) error // 解码到结构体
func DecodeStructFast(data []byte, v interface{}) error // 快速解码
func (n Node) Decode(v any) error // Node 解码基础示例:
// 定义结构体
type User struct {
Name string `json:"name"`
Age int `json:"age"`
Active bool `json:"active"`
}
// 序列化
user := User{Name: "张三", Age: 30, Active: true}
jsonBytes := fxjson.FastMarshal(user)
fmt.Printf("JSON: %s\n", jsonBytes)
// 美化序列化
prettyJSON, _ := fxjson.MarshalIndent(user, "", " ")
fmt.Printf("美化 JSON:\n%s\n", prettyJSON)
// 反序列化
var newUser User
err := fxjson.DecodeStruct(jsonBytes, &newUser)
if err == nil {
fmt.Printf("用户: %+v\n", newUser)
}
// Node 转 JSON
node := fxjson.FromString(`{"id": 1, "name": "test"}`)
jsonStr, _ := node.ToJSON()
fmt.Printf("JSON: %s\n", jsonStr)深度遍历
Walk()
func (n Node) Walk(fn func(path string, node Node) bool)递归遍历 JSON 的所有节点,适合复杂数据结构的分析。
json := `{
"company": "Tech Corp",
"departments": {
"engineering": {
"count": 25,
"teams": ["backend", "frontend"]
}
}
}`
node := fxjson.FromString(json)
// 深度遍历所有节点
node.Walk(func(path string, n fxjson.Node) bool {
if n.IsString() {
fmt.Printf("%s = %s (字符串)\n", path, n.StringOr(""))
} else if n.IsNumber() {
fmt.Printf("%s = %d (数字)\n", path, n.IntOr(0))
} else if n.IsArray() {
fmt.Printf("%s = 数组(长度: %d)\n", path, n.Len())
}
return true // 继续遍历
})配置选项
ParseOptions
type ParseOptions struct {
MaxDepth int // 最大嵌套深度,0 表示无限制
MaxStringLen int // 最大字符串长度,0 表示无限制
MaxObjectKeys int // 最大对象键数量,0 表示无限制
MaxArrayItems int // 最大数组项数量,0 表示无限制
StrictMode bool // 严格模式:拒绝格式错误的 JSON
}默认配置:
var DefaultParseOptions = ParseOptions{
MaxDepth: 1000, // 最大1000层嵌套
MaxStringLen: 1024 * 1024, // 最大1MB字符串
MaxObjectKeys: 10000, // 最大10000个键
MaxArrayItems: 100000, // 最大100000个数组项
StrictMode: false, // 非严格模式
}JsonParam(序列化选项)
type JsonParam struct {
Indent int // 缩进空格数;0 表示紧凑模式
EscapeHTML bool // 是否转义 HTML 符号
Precision int // 浮点数精度;-1 表示原样输出
}性能特性
零分配操作
以下操作在 FxJSON 中是零内存分配的:
Get()/GetPath()访问ArrayForEach()/ForEach()遍历StringOr()/IntOr()/FloatOr()/BoolOr()转换IsString()/IsNumber()等类型检查Len()/Index()/Exists()等基础操作
缓存机制
FxJSON 内置智能缓存:
- 数组索引访问会被缓存,重复访问速度提升 4 倍
- 缓存是线程安全的,无锁设计
- 基于指针+范围的键,内存效率高
json := `{"users": [{"name": "张三"}, {"name": "李四"}]}`
node := fxjson.FromString(json)
// 第一次访问,建立缓存
name1 := node.GetPath("users.0.name").StringOr("")
// 第二次访问,使用缓存,速度快 4 倍
name1Again := node.GetPath("users.0.name").StringOr("")错误处理指南
推荐模式:使用 Or 方法
// 优雅的错误处理,无需 if err != nil
name := node.Get("name").StringOr("默认用户")
age := node.Get("age").IntOr(0)
active := node.Get("active").BoolOr(false)严格模式:手动错误处理
// 需要明确错误信息时使用
name, err := node.Get("name").String()
if err != nil {
switch err := err.(type) {
case *fxjson.FxJSONError:
fmt.Printf("JSON错误: %s (位置: %d行%d列)\n",
err.Error(), err.Position.Line, err.Position.Column)
default:
fmt.Printf("未知错误: %v\n", err)
}
return
}字段存在性检查
// 检查字段是否存在
if node.Get("optional").Exists() {
value := node.Get("optional").StringOr("")
// 处理存在的字段
}
// 检查并获取值的组合用法
email := node.Get("email")
if email.Exists() && email.IsValidEmail() {
fmt.Printf("有效邮箱: %s\n", email.StringOr(""))
}最佳实践
1. 优先使用安全方法
// 推荐:简洁且安全
name := node.Get("user").Get("name").StringOr("匿名")
// 不推荐:代码冗余
userNode := node.Get("user")
nameNode := userNode.Get("name")
name, err := nameNode.String()
if err != nil {
name = "匿名"
}2. 合理使用路径访问
// 深层嵌套时使用路径访问
city := node.GetPath("user.profile.address.city").StringOr("")
// 浅层访问时链式调用更清晰
name := node.Get("user").Get("name").StringOr("")3. 高效的遍历方式
// 推荐:零分配高性能遍历
users.ArrayForEach(func(i int, user fxjson.Node) bool {
processUser(user)
return true
})
// 不推荐:传统索引遍历
for i := 0; i < users.Len(); i++ {
user := users.Index(i)
processUser(user)
}4. 适当的类型检查
// 处理未知数据时先检查类型
value := node.Get("dynamic_field")
if value.IsString() {
text := value.StringOr("")
// 处理字符串
} else if value.IsNumber() {
num := value.IntOr(0)
// 处理数字
}这就是 FxJSON 的完整 API 参考。从基础的解析和访问,到高级的验证和序列化,FxJSON 都为您提供了简洁高效的解决方案。建议从基础的 Get() 和 StringOr() 方法开始,逐步探索更多功能。