《如何使用Python读写JSON文件》
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,因其易读性、结构化和跨语言支持,成为现代软件开发中最常用的数据格式之一。Python通过内置的json
模块提供了对JSON文件的完整支持,开发者可以轻松实现Python对象与JSON数据的相互转换。本文将系统讲解如何使用Python读写JSON文件,涵盖基础操作、高级技巧以及常见问题的解决方案。
一、JSON与Python数据类型的映射关系
在开始操作前,理解JSON与Python数据类型之间的对应关系至关重要。JSON支持的数据类型包括:
- 对象(Object):对应Python的字典(dict)
- 数组(Array):对应Python的列表(list)
- 字符串(String):对应Python的字符串(str)
- 数字(Number):对应Python的整数(int)或浮点数(float)
- 布尔值(true/false):对应Python的True/False
- 空值(null):对应Python的None
这种映射关系是Python处理JSON数据的基础。例如,以下JSON对象:
{
"name": "Alice",
"age": 30,
"is_student": false,
"courses": ["Math", "Science"],
"address": null
}
可以完美转换为Python字典:
{
"name": "Alice",
"age": 30,
"is_student": False,
"courses": ["Math", "Science"],
"address": None
}
二、读取JSON文件
读取JSON文件的核心步骤是:打开文件→读取内容→解析为Python对象。Python的json
模块提供了load()
方法来实现这一过程。
1. 基本读取方法
假设有一个名为data.json
的文件,内容如下:
{
"employees": [
{
"id": 1,
"name": "John Doe",
"department": "IT"
},
{
"id": 2,
"name": "Jane Smith",
"department": "HR"
}
]
}
读取该文件的代码如下:
import json
with open('data.json', 'r', encoding='utf-8') as file:
data = json.load(file)
print(type(data)) # 输出:
print(data['employees'][0]['name']) # 输出: John Doe
关键点说明:
-
with
语句确保文件正确关闭 -
'r'
模式表示读取 -
encoding='utf-8'
指定编码格式,避免中文乱码 -
json.load()
直接将文件内容解析为Python对象
2. 处理JSON字符串
如果数据是以字符串形式存在,可以使用json.loads()
方法:
import json
json_string = '{"name": "Bob", "age": 25}'
python_dict = json.loads(json_string)
print(python_dict['name']) # 输出: Bob
3. 错误处理
JSON解析可能因格式错误而失败,建议使用try-except
块捕获异常:
import json
invalid_json = '{"name": "Alice", "age": }' # 缺少值的错误JSON
try:
data = json.loads(invalid_json)
except json.JSONDecodeError as e:
print(f"JSON解析错误: {e}")
# 输出: JSON解析错误: Expecting value: line 1 column 21 (char 20)
三、写入JSON文件
将Python对象写入JSON文件的过程与读取相反:创建Python对象→转换为JSON字符串→写入文件。主要使用json.dump()
或json.dumps()
方法。
1. 基本写入方法
以下示例演示如何将Python字典写入JSON文件:
import json
data = {
"product": "Laptop",
"price": 999.99,
"in_stock": True,
"specs": {
"CPU": "i7",
"RAM": "16GB"
}
}
with open('product.json', 'w', encoding='utf-8') as file:
json.dump(data, file, indent=4) # indent参数用于美化输出
生成的product.json
文件内容:
{
"product": "Laptop",
"price": 999.99,
"in_stock": true,
"specs": {
"CPU": "i7",
"RAM": "16GB"
}
}
2. 格式化输出
json.dump()
和json.dumps()
都支持以下格式化参数:
-
indent
:指定缩进空格数,使输出更易读 -
sort_keys
:按字母顺序排序键 -
ensure_ascii
:设为False可保留非ASCII字符(如中文)
示例:
import json
data = {
"城市": "北京",
"人口": 2171
}
json_string = json.dumps(data, indent=2, ensure_ascii=False, sort_keys=True)
print(json_string)
输出:
{
"人口": 2171,
"城市": "北京"
}
3. 处理JSON字符串
使用json.dumps()
将Python对象转换为JSON字符串:
import json
person = {
"name": "Alice",
"age": 30,
"hobbies": ["reading", "swimming"]
}
json_str = json.dumps(person)
print(json_str) # 输出: {"name": "Alice", "age": 30, "hobbies": ["reading", "swimming"]}
四、高级应用技巧
1. 自定义对象编码
默认情况下,Python的自定义对象无法直接转换为JSON。可以通过实现default
参数或继承json.JSONEncoder
类来解决。
方法一:使用default
参数
import json
from datetime import datetime
def custom_encoder(obj):
if isinstance(obj, datetime):
return obj.isoformat()
raise TypeError(f"Object of type {obj.__class__.__name__} is not JSON serializable")
data = {
"event": "Conference",
"date": datetime.now()
}
json_str = json.dumps(data, default=custom_encoder)
print(json_str)
方法二:继承JSONEncoder
import json
from datetime import datetime
class CustomEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime):
return obj.isoformat()
return super().default(obj)
data = {
"event": "Workshop",
"date": datetime.now()
}
json_str = json.dumps(data, cls=CustomEncoder)
print(json_str)
2. 处理大数据量
当处理大型JSON文件时,逐行读取或使用生成器可以提高效率。对于JSON Lines格式(每行一个JSON对象),可以这样处理:
import json
def read_json_lines(file_path):
with open(file_path, 'r', encoding='utf-8') as file:
for line in file:
yield json.loads(line.strip())
for item in read_json_lines('large_data.jsonl'):
print(item['id']) # 假设每个对象都有id字段
3. JSON Schema验证
使用第三方库如jsonschema
可以验证JSON数据是否符合预期结构:
import json
from jsonschema import validate
schema = {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "number", "minimum": 0}
},
"required": ["name"]
}
data = {"name": "Alice", "age": 30}
try:
validate(instance=data, schema=schema)
print("数据验证通过")
except Exception as e:
print(f"验证错误: {e}")
五、常见问题解决方案
1. 中文编码问题
问题表现:中文显示为Unicode转义序列(如\u4e2d\u6587)
解决方案:
# 写入时
json.dump(data, file, ensure_ascii=False, indent=2)
# 读取时无需特殊处理,Python会自动解码
2. 日期时间处理
问题:datetime对象无法直接序列化
解决方案:
# 方法1:转换为字符串
data = {
"created_at": datetime.now().isoformat()
}
# 方法2:使用自定义编码器(见高级技巧部分)
3. 大数字精度丢失
问题:JSON默认将所有数字视为浮点数,可能导致大整数精度丢失
解决方案:
import json
from decimal import Decimal
data = {
"big_number": Decimal("12345678901234567890")
}
# 需要自定义编码器将Decimal转为字符串
def decimal_encoder(obj):
if isinstance(obj, Decimal):
return str(obj)
raise TypeError(f"Object of type {obj.__class__.__name__} is not JSON serializable")
json_str = json.dumps(data, default=decimal_encoder)
print(json_str)
4. 性能优化
对于超大JSON文件,考虑使用orjson
等第三方库,它们提供更快的序列化/反序列化速度:
import orjson
data = {"key": "value"}
json_bytes = orjson.dumps(data) # 返回bytes而非str
json_str = json_bytes.decode('utf-8')
六、最佳实践总结
- 始终使用
with
语句处理文件,确保资源正确释放 - 明确指定文件编码(推荐utf-8)
- 对用户提供的JSON数据进行严格验证
- 生产环境中添加适当的错误处理
- 考虑使用
indent
参数提高可读性(开发环境) - 对于性能敏感场景,评估第三方库如
orjson
或ujson
关键词
Python、JSON、文件读写、序列化、反序列化、json模块、数据交换、JSONDecodeError、自定义编码、JSON Schema、性能优化
简介
本文详细介绍了Python中处理JSON文件的方法,包括基础读写操作、高级技巧如自定义对象编码和大数据处理,以及常见问题的解决方案。通过实际代码示例,读者可以掌握从简单文件操作到复杂数据验证的全流程技能,适用于Web开发、数据分析和API交互等多种场景。