Python 格式化 JSON 完整指南 2026
最后更新:2026年5月16日 · 阅读约10分钟
在 Python 中格式化 JSON 是开发者每天都会遇到的任务。不管是调试 API 响应、保存配置文件,还是生成可读的数据导出,Python 内置的 json 模块都能轻松搞定。这篇指南从基础的美化输出讲到高级的自定义编码器,帮你全面掌握。
快速提示:不想写代码就想格式化 JSON?试试我们的免费 在线 JSON 格式化工具 — 粘贴你的 JSON,立刻得到格式化好的输出。
用 json.dumps 基础格式化 JSON
在 Python 中格式化 JSON 最简单的方式就是用 json.dumps() 配合 indent 参数。这个函数会把 Python 对象转换成 JSON 格式的字符串。
import json
data = {
"name": "Alice",
"age": 30,
"skills": ["Python", "JavaScript", "Go"],
"address": {
"city": "上海",
"country": "中国"
}
}
# 用 2 个空格缩进美化输出
formatted = json.dumps(data, indent=2, ensure_ascii=False)
print(formatted)
输出结果:
{
"name": "Alice",
"age": 30,
"skills": [
"Python",
"JavaScript",
"Go"
],
"address": {
"city": "上海",
"country": "中国"
}
}
indent 参数详解
indent 参数控制每一层嵌套的空格数。常用值:
indent=None— 紧凑输出,无空白字符(默认)indent=2— 每层 2 个空格(Web 开发最常用)indent=4— 每层 4 个空格(Python 项目常用)indent='\t'— 用制表符代替空格
# 紧凑模式(默认)
json.dumps(data)
# '{"name": "Alice", "age": 30, ...}'
# 制表符缩进
json.dumps(data, indent='\t')
# '{\n\t"name": "Alice",\n\t"age": 30,\n\t...
'
用 sort_keys 排序键名
为了输出结果一致、可复现(特别在测试和版本控制中很有用),可以使用 sort_keys 参数:
formatted = json.dumps(data, indent=2, sort_keys=True, ensure_ascii=False)
print(formatted)
这会在每一层嵌套中按字母顺序排列所有键名,方便对比不同运行的 JSON 输出。
用 json.dump 写入文件
json.dumps() 返回字符串,而 json.dump() 直接写入文件对象,处理大数据集时更省内存:
import json
data = {
"users": [
{"id": 1, "name": "小明"},
{"id": 2, "name": "小红"}
],
"total": 2
}
# 写入格式化的 JSON 文件
with open("output.json", "w", encoding="utf-8") as f:
json.dump(data, f, indent=2, ensure_ascii=False)
print("JSON 已写入 output.json")
重要提示:当数据包含非 ASCII 字符(中文、日文、emoji 等)时,一定要用 ensure_ascii=False。否则 你好 会被转义成 \u4f60\u597d。
处理不可序列化的类型
Python 的 json 模块只能序列化基本类型:str、int、float、bool、None、list 和 dict。其他类型需要自定义编码器。
处理 datetime 对象
这是最常见的场景。Python 的 datetime 对象默认不能被 JSON 序列化:
import json
from datetime import datetime, date
class DateTimeEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime):
return obj.isoformat()
if isinstance(obj, date):
return obj.isoformat()
return super().default(obj)
data = {
"event": "Python 大会",
"date": datetime(2026, 6, 15, 9, 0),
"created": date(2026, 1, 1)
}
formatted = json.dumps(data, indent=2, cls=DateTimeEncoder, ensure_ascii=False)
print(formatted)
输出:
{
"event": "Python 大会",
"date": "2026-06-15T09:00:00",
"created": "2026-01-01"
}
处理 Decimal 和其他数值类型
import json
from decimal import Decimal
class SmartEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, Decimal):
return float(obj)
if isinstance(obj, set):
return list(obj)
if isinstance(obj, bytes):
return obj.decode("utf-8")
return super().default(obj)
data = {
"price": Decimal("19.99"),
"tags": {"python", "json", "教程"},
"content": b"Hello World"
}
print(json.dumps(data, indent=2, cls=SmartEncoder, ensure_ascii=False))
使用 default 参数(更简单的方式)
对于一次性场景,可以直接传一个函数给 default 参数,不用创建完整的编码器类:
import json
from datetime import datetime
def serialize(obj):
if isinstance(obj, datetime):
return obj.isoformat()
raise TypeError(f"类型 {type(obj)} 不可序列化")
data = {"timestamp": datetime.now()}
print(json.dumps(data, default=serialize))
控制输出格式
自定义分隔符
separators 参数可以控制元素之间的分隔符。默认是 (', ', ': '):
# 紧凑模式,类似 JavaScript 的 JSON.stringify
compact = json.dumps(data, separators=(',', ':'))
# '{"name":"Alice","age":30}'
# 自定义分隔符
custom = json.dumps(data, separators=(' | ', ' = '))
# '{"name" = "Alice" | "age" = 30}'
保留非 ASCII 字符
data = {"greeting": "你好世界", "emoji": "🐍"}
# 默认:转义非 ASCII 字符
print(json.dumps(data))
# {"greeting": "\u4f60\u597d\u4e16\u754c", "emoji": "\ud83d\udc0d"}
# 用 ensure_ascii=False 保留 Unicode
print(json.dumps(data, ensure_ascii=False, indent=2))
# {
# "greeting": "你好世界",
# "emoji": "🐍"
# }
读取并格式化已有的 JSON 文件
常见的工作流是读取 JSON 文件、可能做些修改、再以格式化的方式写回去:
import json
# 读取、格式化、重写
with open("config.json", "r", encoding="utf-8") as f:
data = json.load(f)
# 可选:修改数据
data["last_modified"] = "2026-05-16"
# 格式化写回
with open("config.json", "w", encoding="utf-8") as f:
json.dump(data, f, indent=2, ensure_ascii=False, sort_keys=True)
进阶:美化已有的 JSON 字符串
如果你已经有一个 JSON 字符串(比如来自 API 响应),想格式化它:
import json
raw_json = '{"name":"Alice","age":30,"skills":["Python","JS"]}'
# 解析后重新格式化
parsed = json.loads(raw_json)
formatted = json.dumps(parsed, indent=2, ensure_ascii=False)
print(formatted)
命令行格式化 JSON
可以把 Python 当作终端里的 JSON 格式化工具:
# 格式化 JSON 文件
python -m json.tool input.json
# 格式化并保存
python -m json.tool input.json > formatted.json
# 从管道格式化
echo '{"a":1,"b":2}' | python -m json.tool
# 指定缩进
python -m json.tool --indent 4 input.json
# 排序键名
python -m json.tool --sort-keys input.json
性能注意事项
处理大型 JSON 文件时,记住以下几点:
- 大数据集用
json.dump()直接写文件,而不是json.dumps()再写入 indent=None(默认)产生的输出最小sort_keys=True有排序开销 — 不需要排序时可以跳过- 超大文件(100MB+)考虑用
ijson库做流式处理
json.dumps 和 json.dump 的区别
json.dumps(obj)— 返回 JSON 字符串json.dump(obj, file)— 直接写入文件
import json
data = {"key": "value"}
# 返回字符串
json_string = json.dumps(data, indent=2)
# 写入文件
with open("out.json", "w") as f:
json.dump(data, f, indent=2)
json.dumps 常用参数速查
indent— 缩进空格数(或制表符)sort_keys—True按字母排序键名ensure_ascii—False保留 Unicode 字符separators—(元素分隔符, 键值分隔符)元组default— 处理不可序列化对象的函数cls— 自定义 JSONEncoder 子类skipkeys—True跳过非字符串键而不是抛出 TypeError
常见问题
如何在 Python 中美化打印 JSON?
用 json.dumps(data, indent=2) 就能得到格式化的 JSON 字符串。也可以用 pprint 模块,但 json.dumps 配合 indent 才是标准的 JSON 格式化方式。
json.dumps 和 json.dump 有什么区别?
json.dumps() 返回 JSON 格式的字符串。json.dump() 直接写入文件对象。需要字符串用 dumps,写文件用 dump。
如何用 4 个空格缩进 JSON?
给 json.dumps() 传 indent=4:json.dumps(data, indent=4)。
如何处理 JSON 中的 datetime 对象?
创建一个继承 json.JSONEncoder 的自定义编码器类,重写 default 方法把 datetime 转成 ISO 格式字符串,然后传 cls=YourEncoder 给 json.dumps()。
为什么 JSON 输出中的中文字符被转义了?
默认情况下 json.dumps 设置 ensure_ascii=True,会转义非 ASCII 字符。加上 ensure_ascii=False 就能保留原始字符。
如何在命令行格式化 JSON?
用 Python 内置模块:python -m json.tool input.json。加 --sort-keys 排序输出,--indent 4 自定义缩进。
在线试试
不想写代码来格式化 JSON?试试我们的 免费在线 JSON 格式化工具 — 粘贴你的 JSON,选择缩进方式,立刻得到格式化输出。无需注册。