首页/数据/数据工程与 ETL 速查/JSON 与 NDJSON 行式文本
管道基础52 条

JSON 与 NDJSON 行式文本

JSON 数组需要整体解析、难以流式处理;NDJSON(每行一个 JSON 对象)可以逐行处理与追加,是日志与事件落地的常见形态。

两种 JSON 形态

JSON 适合做接口响应与配置文件:一个文件就是一个完整文档,结构可以嵌套。但在数据管道里,一个巨大的 JSON 数组必须整体解析完才能取到第一个元素,无法边写边读;NDJSON(也叫 JSON Lines)把每个对象单独写一行,可以逐行解析、逐行追加,写入方与读取方不需要同时在线。日志与事件落地的默认形态基本都是 NDJSON。

基本信息

JSON单文档结构,适合接口响应与配置文件
NDJSON按行分隔的多个 JSON 对象,适合流式与追加写
工具jq 处理、Spark/Flink 原生支持解析
分隔规则一行一个完整对象,行内不能有裸换行
压缩方式可按行压缩后整体 gzip,仍能逐块解压
常见来源应用日志、埋点上报、消息落盘

jq 常用操作

jq 常用操作
head -1 events.ndjson | jq '.'
jq -c 'select(.level == "ERROR") | {ts, msg}' events.ndjson | head
jq -s 'length' events.ndjson       # 统计行数(会把文件读进内存)

# 逐行处理,避免整文件读入内存
while IFS= read -r line; do echo "$line" | jq -r '.ts'; done < events.ndjson | head

典型使用场景

  • 应用日志落地:每行一条日志,追加写不需要重写整个文件
  • 埋点上报:客户端批量上报时按行拼接,服务端逐行写入
  • 消息落盘:从队列消费后原样写入对象存储,保留原始结构便于回溯
  • 增量导入:新增文件只包含新数据,读取时按文件粒度处理
  • 调试与抽查:用 jq 快速过滤与抽取字段,不必写完整程序

常见问题与处理

问题表现处理
字段缺失解析报错或取到空按字符串读入后显式判断
类型漂移同一字段有时字符串有时数字统一转换或按字符串承接
长整型 ID精度丢失、末位变化以字符串存储
大数组文件整读解析内存溢出改用 NDJSON 逐行处理
嵌套过深下游取字段困难落地时打平常用字段
解析 JSON 时字段缺失与类型漂移很常见:先按字符串读入再显式转换,比直接强类型解析更稳。
用 -s(slurp)模式处理大文件会把全部内容读进内存,只适合小文件或确实需要整体聚合的场景。

易错点

  • JSON 数字在部分语言里默认转 double,长整型 ID 会丢精度,解析时用字符串承接
  • 大数组文件用整读方式解析会 OOM,优先 NDJSON 逐行流式处理
  • NDJSON 行内出现未转义的换行,一条记录被拆成两行导致解析失败
  • 直接把原始 JSON 存进数仓表却不定字段类型,后续查询每次都要运行时转换
  • 字段名大小写或下划线风格不统一,下游引用时频繁踩空

数据来源与参考

  • JSON Lines 规范(jsonlines.org)
  • jq 官方手册
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌