Python中使用json.dump时如何保留JSON原有空白格式?
JSON修改后格式丢失问题的解决办法
问题场景
我有一份JSON文件,原始格式是这样的:
{ "NAME": "Billy", "DETAILS" [{ "COLOR": "RED", "NUMBERS": [ 7, 12 ] }, { "COLOR": "BLUE", "NUMBERS": [ 8, 113 ] }] }
用下面的Python代码(基于pathlib)读取并修改,给每个NUMBERS数组添加一个数字:
import json from pathlib import Path def editJSON(file, number): with file.open() as f: data = json.load(f) details = data['DETAILS'] for user in details: paths = user['NUMBERS'] paths.append(number) with file.open('w') as outfile: json.dump(data, outfile, indent=4) print("Added to file: ", file)
结果修改后的JSON格式变了,NAME和DETAILS之间的空行直接消失:
{ "NAME": "Billy", "DETAILS" [{ "COLOR": "RED", "NUMBERS": [ 7, 12, 14 ] }, { "COLOR": "BLUE", "NUMBERS": [ 8, 113, 14 ] }] }
想问问:为啥格式和原始文件不一样?怎么保留原来的空白,只修改NUMBERS相关的内容?
原因分析
Python标准库的json模块从设计上就不关心JSON里的空行、多余空格这类格式细节:
- 解析JSON时会直接忽略所有非语法必需的空白符
json.dump()生成的格式是固定规则的,只会按指定的indent参数添加缩进,完全不会还原原始文件的自定义空行和排版
解决办法
要保住原始格式,不能用“解析成字典再重写”的常规操作,得换两种思路:
1. 直接文本替换(适合结构固定的场景)
如果你的JSON结构不会变动,直接把文件当字符串读取,用正则匹配找到NUMBERS数组的位置,插入新元素即可:
from pathlib import Path import re def editJSON(file, number): content = file.read_text() # 匹配NUMBERS数组最后一个元素的位置,插入新数字 pattern = re.compile(r'(?<=NUMBERS":\s*\[\s*(?:\d+,\s*)*\d+)\s*(?=\s*\])') content = pattern.sub(f",\n {number}", content) file.write_text(content) print("Added to file: ", file)
注意:这种方法只适合结构固定的场景,要是JSON结构有变动,正则可能匹配出错。
2. 使用专门保留格式的JSON库
比如ruamel.json,它能在解析JSON时记录原始的缩进、空行、引号风格等格式信息,写入时还原这些排版,只修改数据内容。
首先安装库:
pip install ruamel.json
然后修改代码:
from pathlib import Path from ruamel.json import JSON def editJSON(file, number): json_handler = JSON(indent=4, preserve_quotes=True) # 读取时同时获取数据和原始格式信息 data, indents, trailing_commas = json_handler.load(file.open()) # 修改目标数据 for detail in data['DETAILS']: detail['NUMBERS'].append(number) # 写入时用原始格式信息还原排版 json_handler.dump(data, file.open('w'), indents=indents, trailing_commas=trailing_commas) print("Added to file: ", file)
这个方法适用性更广,只要是合法JSON,不管结构怎么变,都能保住原始格式。
内容的提问来源于stack exchange,提问作者Trentonamor
相关产品推荐
相关产品推荐

