如何用ijson检测传感器生成的拼接型无效JSON文件?
用ijson检测拼接式无效JSON文件的正确方法
你的场景是传感器生成的非标准JSON文件:多个JSON对象直接拼接,无首尾方括号、对象间无逗号,文件体积可达数百GB,需要用ijson快速检测这类格式,再用jq修复。原有的检测方法存在问题,以下是正确的实现思路和代码:
问题根源
原方法的问题在于:
- 使用
ijson.items(file, 'item', multiple_values=True)时,'item'路径是针对标准JSON数组(如[{}, {}])的元素路径,但拼接式JSON没有数组结构,因此找不到匹配的元素,循环无法执行。 - 移除
multiple_values=True时,ijson会将整个文件视为单个JSON值,解析完第一个对象后遇到第二个对象就会抛出"trailing garbage"错误。
正确检测方法
方法1:基于底层解析器的高效检测(推荐大文件)
利用ijson的basic_parse接口,遍历JSON解析事件,统计顶层对象的数量,无需加载整个文件到内存,适合几百GB的大文件:
import ijson def is_concat_json(file_path): with open(file_path, 'r') as f: # 开启多值解析模式,允许多个顶层JSON值 parser = ijson.basic_parse(f, multiple_values=True) obj_count = 0 try: for event, _ in parser: # 检测到JSON对象的起始标记 if event == 'start_map': obj_count += 1 # 只要找到第二个对象,即可判定为拼接格式 if obj_count >= 2: return True # 处理单个对象的情况:检查是否为标准数组格式 if obj_count == 1: f.seek(0) # 读取文件开头的第一个非空白字符 first_char = f.read(1).strip() # 不是数组开头的'[',则为单对象拼接格式 return first_char != '[' # 无有效JSON对象的情况 return False except ijson.JSONError: # 解析出错,判定为非标准格式(可根据需求调整逻辑) return False
方法2:改进items接口的调用方式
如果需要同时获取解析后的对象,可调整ijson.items的路径参数为空白字符串(匹配所有顶层值),结合multiple_values=True:
import ijson def test_concat_json(file_path): with open(file_path, 'r') as f: try: # 空白路径匹配所有顶层JSON值,multiple_values=True允许多值解析 records = list(ijson.items(f, '', multiple_values=True)) # 多个顶层对象 → 拼接格式 if len(records) > 1: return True # 单个顶层对象 → 检查是否为数组格式 elif len(records) == 1: f.seek(0) first_char = f.read(1).strip() return first_char != '[' # 无有效对象 return False except ijson.JSONError: return False
逻辑说明
- 两种方法都覆盖了两种非标准场景:多个对象直接拼接、单个对象但未包裹在数组中。
- 方法1更适合超大型文件,因为只要检测到第二个对象就立即返回,无需遍历整个文件。
- 检测通过后,你可以用
jq -s . input.json > output.json来修复格式(-s参数会将多个JSON对象合并为一个数组)。
内容的提问来源于stack exchange,提问作者Tony Ennis
相关产品推荐
相关产品推荐

