Python 2解析TXT类JSON数据报错:No JSON object could be decoded
解决Python 2解析含多段类JSON(含ObjectId)文本的ValueError问题
你的报错核心来自三个关键问题:一是文件包含两段独立的JSON对象,但json.load()只能解析单个完整的JSON结构;二是文本中的ObjectId属于MongoDB非标准JSON类型,标准解码器无法识别;三是数据未按行存储且无序,无法直接逐行处理。下面给你分步解决的方案:
第一步:处理非标准ObjectId类型
标准JSON没有ObjectId这个类型,我们需要先把这类格式转换成标准JSON可识别的结构。这里推荐转换成MongoDB的Extended JSON格式(方便后续如果要操作MongoDB),用正则表达式替换即可:
import re def replace_objectid(raw_text): # 将ObjectId("xxx")替换为{"$oid": "xxx"},适配标准JSON解析 return re.sub(r'ObjectId\("([a-f0-9]+)"\)', r'{"$oid": "\1"}', raw_text)
第二步:拆分多段独立JSON对象
因为文件里是两段无序的JSON,我们需要从杂乱的文本中提取出完整的JSON对象。用正则匹配嵌套的{...}结构即可:
def extract_json_objects(raw_text): # 匹配嵌套的JSON对象,正则会自动处理内部的嵌套花括号 json_pattern = re.compile(r'\{(?:[^{}]|(?R))*\}', re.DOTALL) return json_pattern.findall(raw_text)
第三步:重写解析逻辑
结合上面两个步骤,修改你的convert函数,先读取全量文本、处理ObjectId、拆分JSON,再逐个解析:
import json import os import re def replace_objectid(raw_text): return re.sub(r'ObjectId\("([a-f0-9]+)"\)', r'{"$oid": "\1"}', raw_text) def extract_json_objects(raw_text): json_pattern = re.compile(r'\{(?:[^{}]|(?R))*\}', re.DOTALL) return json_pattern.findall(raw_text) def convert(filename): data_list = [] print "Opening TXT file: ", filename with open(filename, 'r') as f: raw_content = f.read() # 预处理ObjectId processed_content = replace_objectid(raw_content) # 提取所有独立的JSON对象 json_strings = extract_json_objects(processed_content) # 逐个解析并捕获异常 for idx, json_str in enumerate(json_strings): try: data = json.loads(json_str) data_list.append(data) print("Parsed JSON object {}: {}".format(idx+1, data)) except ValueError as e: print("Failed to parse JSON object {}: {}".format(idx+1, e)) return data_list if __name__ == '__main__': for dirname, dirnames, filenames in os.walk('../txt'): for filename in filenames: file_path = os.path.join(dirname, filename) print("Processing file: {}".format(file_path)) convert(file_path)
额外提示
- 如果你后续需要将数据写入MongoDB,可以直接使用
bson.json_util的loads方法,它能直接解析{"$oid": "xxx"}格式:from bson import json_util data = json_util.loads(json_str) - 如果你的JSON是数组包裹的形式(比如
[{}, {}]),那可以跳过拆分步骤,直接用json.loads解析处理后的全量文本即可。
内容的提问来源于stack exchange,提问作者kerberos
相关产品推荐
相关产品推荐

