不能。gjson是纯内存解析器,需一次性将整个json加载进内存,几百mb文件调用os.readfile即oom;流式解析应使用json.decoder+token()/skip()或megajson/scanner等真正流式方案。

gjson 能不能用于大 JSON 文件流式解析?
不能。gjson 是纯内存解析器,它要求整个 JSON 字符串或 []byte 一次性加载进内存,再做词法扫描;对几百 MB 的文件,os.ReadFile 就会 OOM,根本轮不到 gjson 开始工作。
常见错误现象:fatal error: runtime: out of memory 或进程被系统 kill —— 这不是 gjson 的 bug,而是用错了场景。
- gjson 适合:HTTP 响应体(
- gjson 不适合:日志导出文件、ETL 输出的巨型数组、本地
data.json(>50MB) - 替代方案:真正流式处理必须用
json.Decoder+Token()/Skip(),或第三方流式 scanner(如megajson/scanner)
想从大 JSON 中只提取 title 字段,该用什么?
如果目标明确(比如只取所有 "title" 字符串值),不要解析整棵树,直接用 token 扫描最省内存。
核心逻辑是识别 TSTRING → TCOLON → TSTRING 这个三元组模式,跳过其他所有结构:
- 用
decoder.Token()逐个读 token,记录前一个 token 类型 - 当上一个是
"title"(string类型)且当前是:(json.Delim),就说明下一个 token 是它的值 - 若下一个 token 是
string,用decoder.Buffered().Bytes()截取原始字节,避免分配新字符串 - 遇到
{、[等容器 token,调用decoder.Skip()跳过整块,不构造 Go 值
这样内存恒定在 KB 级,无论文件是 100MB 还是 2GB。
语言学习场景下如何安全处理脏 JSON?
学习语料常混杂字段缺失、类型错位(比如 "score": "95" 有时是 string,有时是 number)、嵌套深度不一 —— 这些都会让 json.Unmarshal 或强结构体解析 panic。
- 首选
json.RawMessage:把不确定字段(如"example"、"translation")声明为RawMessage,只存引用,不反序列化 - 用
map[string]json.RawMessage接收动态 key,但要限制 key 长度(防恶意超长 key 耗尽内存) - 字段存在性检查必须用
result.Exists(),而不是result.String() != ""—— 空字符串是合法值 - 若必须用 gjson 做快速验证,先
gjson.Valid(data),再gjson.GetBytes(data, "path"),避免 string 转换开销
为什么 decoder.More() 容易卡死或 panic?
dec.More() 不是万能循环开关,它只在已进入数组或对象内部时有效;调用前没确认上下文,就会返回 false 或 panic。
- 错误写法:
for dec.More() { dec.Decode(&item) }—— 如果顶层不是数组,dec.More()直接 panic:invalid operation: More not valid in this state - 正确顺序:先
dec.Token()检查是否为[,再进for dec.More()循环;每次循环末尾必须调用dec.Decode(&item),否则More()不推进状态 - 注意:最后一次
dec.More()返回false后,下一次dec.Token()会返回]或},需显式检查并跳出 - 别依赖
io.EOF判断数组结束 ——dec.Decode()在数组末尾不会返回 EOF,EOF 只在流真正结束时出现
真正难的不是写对第一行,而是确保每一层容器边界都手动对齐;少一次 Skip() 或多一次 Decode(),后续 token 流就全乱了。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











