和普通 JSON 差在哪
普通 JSON 文件是一个值,通常是对象或数组。JSONL 是多行,每行必须是独立的合法 JSON,行与行之间没有逗号,外面也没有 [ ]。
{"ts":"2026-08-29T01:12:03Z","level":"info","msg":"checkout start","order_id":"A1"}
{"ts":"2026-08-29T01:12:04Z","level":"error","msg":"payment timeout","order_id":"A1"}
若你把它包成数组,才是普通 JSON:
[
{"ts":"2026-08-29T01:12:03Z","level":"info","msg":"checkout start","order_id":"A1"},
{"ts":"2026-08-29T01:12:04Z","level":"error","msg":"payment timeout","order_id":"A1"}
]
日志不用数组,是因为可以边写边追加,不用改文件开头的 [,也不用在上一行末尾补逗号。采集器按行切,坏一行不至于整文件作废。
一行里不要折行
JSONL 的约定是:一个对象不占用多行。对象内部如果有字符串换行,必须是 \\n,不能在文件里真的回车。否则「按行切」会切到半个对象,后面全乱。
有的框架 pretty-print 日志,输出多行 JSON。那种不是 JSONL,是「人类可读的日志」,要用别的方式切(空行、正则、或采集器的 multiline)。不要和 JSONL 混谈。
在 HiJSON 里怎么看
- 把导出文件存成
.jsonl,拖到 首页 上传区。也支持.json/.txt。 - 只关心一条事件:从日志里复制那一行,粘贴后解析。不要连粘 200 行当一个文档。
- 已经收成数组的,用
$.[?(@.level=='error')]或$[*].order_id筛。语法见 JSONPath。
文件特别大时,先在本机 grep / jq -c 抽出相关行,再贴进来。浏览器不是日志平台,见 大 JSON。
从平台复制时的脏数据
本机快速切一行(可选)
已经装了 jq 的话:
jq -c 'select(.level=="error")' app.jsonl jq -c '.order_id' app.jsonl
-c 保持紧凑一行,方便再导入。没装 jq 就用编辑器按行跳,或 grep order_id app.jsonl。
和「一次 API 响应」的工作流别混
API 响应是一个文档,适合整段解析、树、大纲。日志是流,适合按行。硬把 5000 行 JSONL 拼成一个数组再展开,树会卡,收益也不大。先缩小到「和这个 order_id 有关的几行」,再展开对象看 stack 或 context。
常见问题
- 中间空一行算不算坏文件?
- 多数实现会跳过空行。保险起见导出时不要留空行,采集器配置也不要随手加。
- UTF-8 BOM 只出现在第一行?
- 是。第一行解析失败、后面都正常,优先查 BOM,见语法错误文。