Python json 模块深度解析:loads() 与 dumps() 全场景指南
(一)一、模块概述
Python 标准库中的 json 模块提供了 json.loads()(JSON 字符串转 Python 对象)和 json.dumps()(Python 对象转 JSON 字符串)两个核心函数,是处理 JSON 数据的核心工具。本文将从基础用法到高级场景,全面解析这两个函数的使用技巧。
(二)二、核心函数详解
1.2.1 json.dumps():Python 对象 → JSON 字符串
功能:将 Python 字典、列表等可序列化对象转换为 JSON 格式字符串。
(1)2.1.1 基础用法示例
import json
# 定义 Python 对象(字典)
data = {
"name": "张三",
"age": 30,
"is_student": False,
"courses": ["数学", "英语"]
}
# 转换为 JSON 字符串
json_str = json.dumps(data)
print(json_str)
# 输出:{"name": "张三", "age": 30, "is_student": false, "courses": ["数学", "英语"]}
(2)2.1.2 常用参数详解
参数 |
类型 |
作用 |
示例 |
indent |
int/None |
控制缩进空格数(美化输出),None 表示无缩进 |
json.dumps(data, indent=4) → 输出带 4 空格缩进的 JSON |
ensure_ascii |
bool |
是否转义非 ASCII 字符(默认 True),False 保留原字符 |
json.dumps(data, ensure_ascii=False) → 中文直接显示,不转义为 \u |
sort_keys |
bool |
是否按字典键排序(默认 False) |
json.dumps(data, sort_keys=True) → 键按字母顺序排列 |
separators |
tuple |
控制键值对和列表项的分隔符(默认 (', ', ': ')) |
json.dumps(data, separators=(',', ':')) → 紧凑输出(无空格) |
default |
function |
自定义序列化规则(处理默认无法序列化的对象,如日期、自定义类) |
见下文「高级用法」示例 |
(3)2.1.3 高级用法场景
场景1:序列化日期对象
Python 内置的 datetime 对象无法直接序列化,需通过 default 参数定义规则:
from datetime import datetime
def serialize_datetime(obj):
if isinstance(obj, datetime):
return obj.isoformat() # 转换为 ISO 8601 格式(如 "2025-06-18T14:30:00")
raise TypeError(f"对象 {type(obj)} 无法序列化")
data = {"event": "会议", "time": datetime.now()}
json_str = json.dumps(data, default=serialize_datetime)
# 输出:{"event": "会议", "time": "2025-06-18T14:30:00.123456"}
场景2:紧凑输出(减少体积)
通过 separators 去除冗余空格,适用于网络传输或存储:
# 紧凑模式(无缩进,键值对无空格)
json_str = json.dumps(data, separators=(',', ':'), indent=None)
# 输出:{"name":"张三","age":30,"is_student":false,"courses":["数学","英语"]}
2.2.2 json.loads():JSON 字符串 → Python 对象
功能:将 JSON 格式字符串解析为 Python 字典、列表等对象。
(1)2.2.1 基础用法示例
json_str = '{"name": "李四", "age": 25, "active": true}'
data = json.loads(json_str) # 解析为 Python 字典
print(data["name"]) # 输出:李四
(2)2.2.2 常用参数详解
参数 |
类型 |
作用 |
示例 |
object_hook |
function |
自定义字典转换规则(将解析后的字典转换为自定义对象) |
见下文「高级用法」示例 |
parse_float |
function |
自定义浮点数解析(覆盖默认的 float() 转换) |
parse_float=lambda x: round(float(x), 2) → 保留两位小数 |
parse_int |
function |
自定义整数解析(覆盖默认的 int() 转换) |
parse_int=lambda x: int(x, 16) → 解析十六进制字符串为整数 |
parse_constant |
function |
处理特殊常量(如 Infinity、NaN、-Infinity) |
自定义异常处理,防止恶意输入 |
(3)2.2.3 高级用法场景
场景1:解析为自定义对象
通过 object_hook 将 JSON 字典转换为 Python 类实例:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def dict_to_person(d):
if "name" in d and "age" in d:
return Person(d["name"], d["age"]) # 转换为 Person 对象
return d # 其他字典保持不变
json_str = '{"name": "王五", "age": 28}'
person = json.loads(json_str, object_hook=dict_to_person)
print(type(person)) # 输出:<class '__main__.Person'>
场景2:自定义数值解析
通过 parse_float 和 parse_int 调整数值解析规则:
json_str = '{"price": "12.3456", "hex": "0xff"}'
# 解析浮点数时保留两位小数,解析整数时自动检测进制(0x 开头为十六进制)
data = json.loads(
json_str,
parse_float=lambda x: round(float(x), 2), # 12.3456 → 12.35
parse_int=lambda x: int(x, 0) # 自动检测进制(0xff → 255)
)
print(data) # 输出:{'price': 12.35, 'hex': 255}
(三)三、JSON 与 Python 类型对应关系
JSON 与 Python 的数据类型存在严格的映射规则,需特别注意以下几点:
JSON 类型 |
Python 类型 |
说明 |
object |
dict |
JSON 对象始终转换为 Python 字典 |
array |
list |
JSON 数组始终转换为 Python 列表 |
string |
str |
JSON 字符串转换为 Python 字符串 |
number(int) |
int |
JSON 整数转换为 Python 整数 |
number(real) |
float |
JSON 浮点数转换为 Python 浮点数 |
true |
True |
JSON 布尔值 true 转换为 Python True |
false |
False |
JSON 布尔值 false 转换为 Python False |
null |
None |
JSON null 转换为 Python None |
(四)四、异常处理与调试
1.4.1 常见异常类型
- json.JSONDecodeError:JSON 字符串格式错误(如缺少引号、括号不匹配)。
- TypeError:尝试序列化无法被 JSON 支持的对象(如 datetime、自定义类实例)。
2.4.2 异常处理示例
import json
from datetime import datetime
# 示例1:处理 JSON 解析错误
try:
invalid_json = '{"name": "错误格式", age: 25}' # 缺少引号的 "age"
data = json.loads(invalid_json)
except json.JSONDecodeError as e:
print(f"解析失败:{e.msg}(行 {e.lineno}, 列 {e.colno})")
# 输出:解析失败:Expecting property name enclosed in double quotes(行 1, 列 12)
# 示例2:处理序列化失败
try:
data = {"time": datetime.now()} # datetime 对象无法直接序列化
json_str = json.dumps(data)
except TypeError as e:
print(f"序列化失败:{e}")
# 输出:序列化失败:Object of type datetime is not JSON serializable
(五)五、性能优化技巧
1.5.1 减少冗余输出
通过 separators 和 indent=None 生成紧凑的 JSON 字符串,降低传输或存储体积:
# 紧凑模式(无缩进,无空格)
json_str = json.dumps(data, separators=(',', ':'), indent=None)
2.5.2 使用高性能库替代
对于高频或大数据量场景,可使用第三方库 orjson(比标准库快 2-3 倍):
import orjson # 需通过 pip install orjson 安装
data = {"name": "高效解析", "value": 100}
# 序列化(返回 bytes 类型)
json_bytes = orjson.dumps(data)
# 反序列化
data = orjson.loads(json_bytes)
3.5.3 避免重复解析
对同一 JSON 字符串多次解析时,优先解析一次后复用结果:
# 低效:重复解析
data1 = json.loads(json_str)
data2 = json.loads(json_str)
# 高效:解析一次,重复使用
parsed_data = json.loads(json_str)
data1 = parsed_data
data2 = parsed_data
(六)六、实际应用场景
1.6.1 配置文件读写
# 读取配置文件
with open("config.json", "r") as f:
config = json.load(f) # 等价于 json.loads(f.read())
# 写入配置文件(美化输出)
with open("config.json", "w") as f:
json.dump(config, f, indent=2) # 等价于 f.write(json.dumps(config, indent=2))
2.6.2 API 数据处理
通过 requests 库获取 API 数据并解析:
import requests
response = requests.get("https://api.example.com/data")
data = json.loads(response.text) # 手动解析
# 或直接使用 requests 内置的 json() 方法(等价于 json.loads(response.text))
data = response.json()
3.6.3 自定义类的序列化与反序列化
为自定义类添加 to_json() 和 from_json() 方法,实现对象的持久化:
class User:
def __init__(self, name, email):
self.name = name
self.email = email
def to_json(self):
return json.dumps(self.__dict__) # 序列化对象属性
@classmethod
def from_json(cls, json_str):
data = json.loads(json_str)
return cls(**data) # 反序列化为对象实例
# 使用示例
user = User("张三", "zhangsan@example.com")
json_str = user.to_json() # 输出:'{"name": "张三", "email": "zhangsan@example.com"}'
new_user = User.from_json(json_str)
(七)总结
json.loads() 和 json.dumps() 是 Python 处理 JSON 数据的核心工具,通过灵活使用参数(如 indent、object_hook)和异常处理,可以覆盖从简单配置到复杂对象的全场景需求。结合性能优化技巧(如使用 orjson),可进一步提升数据处理效率。