
json 本身不支持直接追加,但可通过 json lines(jsonl)格式实现高效、可扩展的日志式写入与读取——每条记录独占一行,避免解析冲突。
json 本身不支持直接追加,但可通过 json lines(jsonl)格式实现高效、可扩展的日志式写入与读取——每条记录独占一行,避免解析冲突。
标准 JSON 是一个完整的、单根的结构化文档(如数组或对象),因此用 'a' 模式反复 json.dump() 会导致多个 JSON 值连续写入同一文件(例如 [...] [...] [...]),这违反了 JSON 语法规范,json.load() 解析时便会抛出 JSONDecodeError: Extra data 错误。
解决方案是采用 JSON Lines(JSONL) 格式:每行一个合法的 JSON 值(无需逗号分隔,自动换行),既保持结构清晰,又天然支持追加写入与流式读取。
✅ 正确实现:JSONL 写入与读取
import json
def write_jsonl(data, filename='test.jsonl'):
"""将数据以 JSONL 格式追加到文件(每条记录一行)"""
with open(filename, 'a', encoding='utf-8') as f:
f.write(json.dumps(data, ensure_ascii=False) + '\n')
def read_jsonl(filename='test.jsonl'):
"""逐行读取并解析 JSONL 文件,返回所有记录组成的列表"""
records = []
with open(filename, 'r', encoding='utf-8') as f:
for line in f:
line = line.strip()
if line: # 跳过空行
records.append(json.loads(line))
return records
# 示例:多次追加任务列表
tasks_batch_1 = [
["1Name", "1c:/path/file.ext", "1Some other text", 10, ["a", "b", "c"], ""],
["2Name", "2c:/path/file.ext", "2Test text", 20, ["a", "b", "c"], ""]
]
tasks_batch_2 = [["3Name", "3c:/path/file.ext", "3New task", 15, ["x", "y"], "done"]]
write_jsonl(tasks_batch_1)
write_jsonl(tasks_batch_2)
# 读取全部历史记录
all_tasks = read_jsonl()
print(f"共加载 {len(all_tasks)} 条记录")
for i, batch in enumerate(all_tasks, 1):
print(f"第 {i} 批:{batch}")
⚠️ 注意事项与最佳实践
- 不要混用 json.dump() 和 print():原示例中 print(json.dumps(...), file=...) 虽可行,但推荐显式拼接 \n(如上),更可控且兼容性更好;
- 编码必须统一:始终指定 encoding='utf-8',避免 Windows 下默认 cp1252 导致中文乱码;
- ensure_ascii=False:保留原始 Unicode 字符(如中文),提升可读性;
- 删除/更新需重写文件:JSONL 不支持随机修改某一行;若需删改,应读取全部内容 → 内存中处理 → 全量重写(或使用数据库替代);
- 替代方案建议:若需高频增删查改,推荐轻量级数据库(如 SQLite、TinyDB)或序列化格式(如 Pickle 仅限 Python 环境内使用)。
JSONL 是日志记录、ETL 流程和配置审计等场景的理想选择——简单、可靠、跨语言兼容,且完全规避了传统 JSON 的追加陷阱。











