如何使用jq解析含MongoDB特殊类型结构的JSON并解决解析报错
问题根因
- 执行
cat mon.json | jq触发的parse error: Invalid numeric literal at line 1, column 493报错,核心原因是mon.json存储的内容并非符合标准规范的JSON格式。 - 该文件内容是MongoDB交互式Shell直接打印的currentOp输出,属于MongoDB自定义的JS化BSON表示,包含
UUID()、BinData()、NumberLong()这类自定义构造函数,完全不兼容jq的严格JSON解析逻辑,因此在非标准结构出现的位置触发“无效数字字面量”的解析报错。你对报错原因的初步判断是准确的。
解析操作方案
jq本身没有内置对MongoDB扩展BSON语法的兼容支持,需要先对文件内的非标准构造做前置清洗,将其转换为标准JSON语法后,再交给jq解析,整个流程不需要安装第三方依赖。
- 针对文件中出现的三类特殊构造,可按照以下规则编写正则替换逻辑:
- 处理
UUID("xxx")结构:移除外层UUID()包裹,将内部的UUID字符串作为普通JSON字符串存储,替换表达式为s/UUID\("([^"]+)"/"$1"/g - 处理
BinData(0,"xxx")结构:移除外层BinData()的参数包裹,将内部的base64编码值作为普通JSON字符串存储,替换表达式为s/BinData\([0-9]+,"([^"]+)"\)/"$1"/g - 处理
NumberLong(数字)结构:移除外层NumberLong()包裹,保留内部的纯数字值作为JSON数字类型,替换表达式为s/NumberLong\((\d+)\)/$1/g
- 处理
- 把上述清洗逻辑与jq执行链路打通,可直接运行的完整命令为:
sed -E 's/UUID\("([^"]+)"/"\1"/g; s/BinData\([0-9]+,"([^"]+)"\)/"\1"/g; s/NumberLong\((\d+)\)/\1/g' mon.json | jq .
拓展注意事项
- 上述清洗逻辑仅适配你当前文件中出现的三类MongoDB特殊构造。如果后续采集的文件中出现
ObjectId()、ISODate()、Timestamp()等其他MongoDB扩展构造,只需要按照相同的逻辑补充对应的正则替换规则,将函数包裹的内部值转换为jq可识别的标准JSON类型,即可继续完成解析。 - 正则清洗属于事后兼容方案,可能存在格式匹配偏差。如果需要高保真的解析结果,更稳妥的方式是在MongoDB端执行currentOp查询时,直接通过
tojson()方法将结果序列化为严格标准JSON后再存入文件,从源头保证格式兼容jq的解析要求,避免后续清洗带来的数据失真。
内容的提问来源于stack exchange,提问作者DB guy
相关产品推荐
相关产品推荐

