Skip to content

迭代方法 ​

Processor 提供多种迭代 JSON 数组和对象的方法。

与包级迭代函数的镜像关系

本页 8 个 Foreach* 方法与包级迭代函数逐条同源,回调签名与迭代语义完全一致,完整示例见包级页。Processor 侧的差异:

  • cfg 语义:可选尾随 cfg 控制该次调用的安全校验(大小、深度、危险模式)等;省略时按处理器自身配置。
  • 缓存保护:迭代根先 Get 再深拷贝出工作副本——回调即使修改 item.GetData() 返回的容器,也不会污染处理器的解析缓存与原输入。
  • 生命周期:处理器关闭后所有迭代方法返回 ErrProcessorClosed。

Foreach ​

已废弃

签名:func (p *Processor) Foreach(jsonStr string, fn func(key any, item *IterableValue), cfg ...Config)

迭代 JSON 数组或对象。

已废弃

Foreach 会静默丢弃错误:文档非法或处理器已关闭时,回调被整体跳过且不返回任何错误,调用方无从得知。请改用 ForeachWithError——它把错误正常返回,且回调返回 nil 表示继续迭代。Foreach 在 v1 生命周期内保留、不会移除。

go
// 已废弃:错误被静默丢弃;新代码请用 ForeachWithError(见下)
p.Foreach(data, func(key any, item *json.IterableValue) {
    fmt.Printf("Key: %v, Value: %v\n", key, item.GetData())
})

迭代数组时:key 为索引(int) 迭代对象时:key 为键名(string)

ForeachWithPath ​

签名:func (p *Processor) ForeachWithPath(jsonStr, path string, fn func(key any, item *IterableValue), cfg ...Config) error

按路径迭代,返回错误。

go
err := p.ForeachWithPath(data, "items", func(key any, item *json.IterableValue) {
    fmt.Printf("[%v] %v\n", key, item.GetData())
})

适用于:

  • 迭代嵌套数组
  • 迭代指定路径的对象

ForeachNested ​

已废弃

签名:func (p *Processor) ForeachNested(jsonStr string, fn func(key any, item *IterableValue), cfg ...Config)

递归迭代所有嵌套层级。

已废弃

ForeachNested 与 Foreach 一样静默丢弃错误:解析失败或处理器已关闭时回调被整体跳过,不返回任何错误。请改用 ForeachNestedWithError——它把错误正常返回,且回调返回 nil 表示继续迭代。ForeachNested 在 v1 生命周期内保留、不会移除。

go
// 已废弃:错误被静默丢弃;新代码请用 ForeachNestedWithError(见下)
p.ForeachNested(data, func(key any, item *json.IterableValue) {
    fmt.Printf("键: %v, 值: %v\n", key, item.GetData())
})

示例数据:

json
{
  "user": {
    "name": "test",
    "profile": {
      "age": 25,
      "tags": ["a", "b"]
    }
  }
}

输出:

text
键:user, 值:map[string]any{...}
键:name, 值:test
键:profile, 值:map[string]any{...}
键:age, 值:25
键:tags, 值:[]any{...}
...

ForeachReturn ​

签名:func (p *Processor) ForeachReturn(jsonStr string, fn func(key any, item *IterableValue), cfg ...Config) (string, error)

迭代 JSON 数据并返回重新序列化后的 JSON 字符串。回调可以修改迭代容器:item.GetData() 返回工作副本(深拷贝)的引用,对 map / slice 的增删改会反映到最终序列化结果;标量无法原地替换。修改不影响原输入与处理器缓存。

go
package main

import (
	"fmt"

	"github.com/cybergodev/json"
)

func main() {
	p, err := json.New()
	if err != nil {
		panic(err)
	}
	defer p.Close()

	data := `[{"id":1,"internal":"x"},{"id":2,"internal":"y"}]`
	result, err := p.ForeachReturn(data, func(key any, item *json.IterableValue) {
		if obj, ok := item.GetData().(map[string]any); ok {
			delete(obj, "internal") // 修改工作副本,写入返回结果
		}
	})
	if err != nil {
		panic(err)
	}
	fmt.Println(result)
	// 输出:[{"id":1},{"id":2}]
}

适用于需要在迭代后继续链式操作的场景。

ForeachWithError ​

签名:func (p *Processor) ForeachWithError(jsonStr, path string, fn func(key any, item *IterableValue) error, cfg ...Config) error

按路径迭代,回调支持返回错误。

go
err := p.ForeachWithError(data, "items", func(key any, item *json.IterableValue) error {
    if item.GetInt("id") == 0 {
        return fmt.Errorf("invalid item at index %v", key)
    }
    return nil // 继续迭代
})

ForeachNestedWithError ​

签名:func (p *Processor) ForeachNestedWithError(jsonStr string, fn func(key any, item *IterableValue) error, cfg ...Config) error

递归迭代所有嵌套层级,回调支持返回错误。

go
err := p.ForeachNestedWithError(data, func(key any, item *json.IterableValue) error {
    fmt.Printf("键: %v, 值: %v\n", key, item.GetData())
    return nil
})

ForeachWithPathAndIterator ​

签名:func (p *Processor) ForeachWithPathAndIterator(jsonStr, path string, fn func(key any, item *IterableValue, currentPath string) IteratorControl, cfg ...Config) error

按路径迭代并提供当前路径信息。使用 IteratorControl 控制迭代流程。

go
err := p.ForeachWithPathAndIterator(data, "items", func(key any, item *json.IterableValue, currentPath string) json.IteratorControl {
    fmt.Printf("路径: %s, 键: %v\n", currentPath, key)
    if item.GetInt("id") == targetID {
        return json.IteratorBreak // 停止迭代
    }
    return json.IteratorNormal // 继续迭代
})

ForeachWithPathAndControl ​

签名:func (p *Processor) ForeachWithPathAndControl(jsonStr, path string, fn func(key any, value any) IteratorControl, cfg ...Config) error

按路径迭代原始值,使用 IteratorControl 控制流程。

go
err := p.ForeachWithPathAndControl(data, "items", func(key any, value any) json.IteratorControl {
    fmt.Printf("键: %v, 值: %v\n", key, value)
    return json.IteratorNormal
})

IterableValue ​

迭代回调中的 IterableValue 提供类型安全的取值能力:Get / GetString / GetInt / GetFloat64 / GetBool / GetArray / GetObject 以及带默认值的变体(GetWithDefault、GetStringWithDefault、GetIntWithDefault 等),状态判断(Exists / IsNull / IsNullData / IsEmpty / IsEmptyData),嵌套迭代 ForeachNested,以及 Break() 中断信号。完整方法清单与逐个说明见 IterableValue 类型详解,与本页回调用法完全一致。

方法对比 ​

方法路径参数递归返回值错误回调
Foreach无否无否
ForeachWithPath有否error否
ForeachNested无是无否
ForeachReturn无否(string, error)否
ForeachWithError有否error是
ForeachNestedWithError无是error是
ForeachWithPathAndIterator有否errorIteratorControl
ForeachWithPathAndControl有否errorIteratorControl

文件迭代方法 ​

Processor 提供直接从文件迭代的方法,是 LoadFromFile + Foreach 系列的便捷组合:路径安全校验、MaxJSONSize 读取限制与 per-call cfg 透传均与文件加载行为一致;文件同样会先整载内存再迭代(受 MaxJSONSize 上限约束,默认 100MB),恒定内存场景见大文件处理。

方法签名要点语义
ForeachFile(filePath, fn, cfg...)迭代文件根级数组 / 对象
ForeachFileWithPath(filePath, path, fn, cfg...)迭代文件中指定路径下的集合
ForeachFileChunked(filePath, chunkSize, fn, cfg...)按批迭代根级数组(chunkSize ≤0 时默认 100);根非数组时报 ErrTypeMismatch
ForeachFileNested(filePath, fn, cfg...)递归迭代所有嵌套结构

回调均为 func(key any, item *json.IterableValue) error:返回 nil 继续、item.Break() 干净停止、其他错误中断并返回。逐方法完整示例见包级迭代页(仅多一个尾随 cfg,行为一致),方法选择表见文件操作。

go
err := p.ForeachFile("data.json", func(key any, item *json.IterableValue) error {
    fmt.Printf("[%v] %v\n", key, item.GetData())
    return nil // 继续迭代
})

文件迭代方法对比 ​

方法路径参数递归分块适合场景
ForeachFile无否否简单文件遍历
ForeachFileWithPath有否否定点遍历
ForeachFileChunked无否是批量落库、分批回调(文件仍整载内存)
ForeachFileNested无是否深度遍历所有节点

迭代控制 ​

回调返回 item.Break() 可干净中断迭代(整体返回 nil);返回其他错误立即中断并原样返回该错误。带路径信息的两个变体(ForeachWithPathAndIterator / ForeachWithPathAndControl)通过 IteratorControl 常量(json.IteratorNormal / json.IteratorBreak)控制流程——日常场景优先用 item.Break()。示例与常量说明见包级迭代页。

go
err := p.ForeachFile("data.json", func(key any, item *json.IterableValue) error {
    if item.GetInt("id") == targetID {
        return item.Break() // 找到目标,干净停止
    }
    return nil // 继续迭代
})

相关 ​