Python 处理 JSON 的入口是标准库 json 模块:dumps/loads 面向字符串,dump/load 面向文件;复杂对象可通过继承 JSONEncoder/JSONDecoder 并配合 cls 参数完成定制。下面按实际开发中最常见的四类操作整理。
一、字符串编解码:dumps 与 loads- import json
- data = {'name': 'Alice', 'age': 25}
- json_str = json.dumps(data)
- print(json_str) # 输出:{"name": "Alice", "age": 25}
- json_str = '{"name": "Alice", "age": 25}'
- data = json.loads(json_str)
- print(data) # 输出:{'name': 'Alice', 'age': 25}
复制代码
dumps 将 Python 字典/列表等对象变成 JSON 字符串,经常用于 Web API 传输;dumps 还能通过缩进、排序键等选项改善可读性。loads 则把收到的 JSON 字符串还原成 Python 对象,方便后续按键访问。
二、文件读写:load 与 dump- import json
- with open('data.json', 'r') as f:
- data = json.load(f)
- print(data)
- data = {'name': 'Alice', 'age': 25}
- with open('data.json', 'w') as f:
- json.dump(data, f)
复制代码
json.load 从文件对象读取并反序列化,json.dump 把 Python 对象序列化后写入文件。和字符串版方法相比,这两者更适合配置、缓存、离线数据等需要持久化的场景,读取的是文件内容而不是内存字符串。
三、自定义编码器和解码器
当对象不是 dict/list/字符串/数字这些 JSON 原生类型时,直接 dumps 会报错。原文做法是定义 Person,再继承 json.JSONEncoder 重写 default;解码侧继承 json.JSONDecoder 重写 decode,并在 dumps/loads 时用 cls 指定。- import json
- class Person:
- def __init__(self, name, age):
- self.name = name
- self.age = age
- class PersonEncoder(json.JSONEncoder):
- def default(self, obj):
- if isinstance(obj, Person):
- return {'name': obj.name, 'age': obj.age}
- return super().default(obj)
- class PersonDecoder(json.JSONDecoder):
- def decode(self, s):
- data = super().decode(s)
- if 'name' in data and 'age' in data:
- return Person(data['name'], data['age'])
- return data
- person = {'person': Person('Alice', 25)}
- json_str = json.dumps(person, cls=PersonEncoder)
- print(json_str) # 输出:{"person": {"name": "Alice", "age": 25}}
- json_data = '{"name": "Alice", "age": 25}'
- obj = json.loads(json_data, cls=PersonDecoder)
- print(obj) # 输出:<__main__.Person object at 0x...>
复制代码
这里要注意:上面的 PersonDecoder.decode 只判断顶层是否同时存在 name 和 age,因此它适合解码顶层就是 {"name":"Alice","age":25} 的 JSON。如果数据是 {"person":{"name":"Alice","age":25}} 这种嵌套结构,loads 后内层仍是普通 dict,不会自动变成 Person;需要按真实结构在 decode/default 里处理嵌套,或者把解码 JSON 调整成顶层 name/age。编码侧则通过 PersonEncoder 把 Person 实例转成普通 dict,因此 dumps 能得到标准 JSON。
四、读取、修改 JSON 值- import json
- json_str = '{"name": "Alice", "age": 25}'
- data = json.loads(json_str)
- print(data['name']) # 输出:Alice
- print(data['age']) # 输出:25
- data['age'] = 26
- json_str = json.dumps(data)
- print(json_str) # 输出:{"name": "Alice", "age": 26}
复制代码
反序列化后,JSON 对象在 Python 中通常就是 dict,所以读取值就是普通键访问;修改值时先改 dict,再用 dumps 转回 JSON 字符串即可。这种模式适合动态调整请求体、配置项或接口返回数据。
五、用 get 提供默认值,避免 KeyError- import json
- json_str = '{"name": "Alice", "age": 25}'
- json_obj = json.loads(json_str)
- name = json_obj.get('name', 'Unknown')
- print(name) # 输出:Alice
- gender = json_obj.get('gender', 'Unknown')
- print(gender) # 输出:Unknown
复制代码
如果直接用 json_obj['gender'],键不存在时会抛 KeyError。dict.get(key, default) 会在键存在时返回实际值,不存在时返回默认值。对接口字段可能缺失、数据清理不彻底或旧版本兼容场景,这个写法能减少程序因缺键崩溃的情况,提高健壮性。
总结:json 模块的 dumps/loads 负责字符串编解码,dump/load 负责文件持久化;自定义 JSONEncoder/JSONDecoder 加上 cls 参数可以处理 Person 这类非原生类型;反序列化后按键读取、修改再序列化,是 Web API 与数据存储传输中的常见流程;对可能缺失的键使用 get 提供默认值,是简单直接的容错手段。 |