pin_drop当前位置:知识文库 ❯ 图文
json.load详解 - Python从文件读取JSON数据完整指南
概述
json.load() 是 json 模块中从文件对象读取 JSON 数据并反序列化为 Python 对象的函数。与 loads() 不同,load() 直接从文件流读取数据,无需先将文件内容读入字符串,在处理大文件时更节省内存。load() 的参数与 loads() 基本一致,额外接受一个文件对象参数。
语法
代码示例
import json
obj = json.load(fp, *, cls=None, object_hook=None,
parse_float=None, parse_int=None,
parse_constant=None, object_pairs_hook=None, **kw)参数说明
返回值
返回从文件解析的 Python 对象,类型取决于 JSON 内容(dict、list、str、int、float、bool、None)。
代码示例
示例1:从文件读取JSON
代码示例
import json
import os
# 先创建测试文件
data = {"name": "张三", "age": 25, "skills": ["Python", "Java"]}
with open("user.json", "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
# 从文件读取
with open("user.json", "r", encoding="utf-8") as f:
loaded = json.load(f)
print(f"类型: {type(loaded).__name__}")
print(f"姓名: {loaded['name']}")
print(f"年龄: {loaded['age']}")
print(f"技能: {loaded['skills']}")输出:
代码示例
类型: dict
姓名: 张三
年龄: 25
技能: ['Python', 'Java']示例2:使用object_hook处理日期
代码示例
import json
from datetime import datetime
def date_hook(obj):
"""自动转换ISO日期字符串"""
for key, value in obj.items():
if isinstance(value, str) and 'T' in value:
try:
obj[key] = datetime.fromisoformat(value)
except ValueError:
pass
return obj
# 创建带日期的JSON文件
log_data = {
"events": [
{"action": "login", "time": "2024-01-15T09:00:00"},
{"action": "logout", "time": "2024-01-15T18:00:00"},
]
}
with open("events.json", "w", encoding="utf-8") as f:
json.dump(log_data, f, ensure_ascii=False, indent=2)
# 使用object_hook读取
with open("events.json", "r", encoding="utf-8") as f:
result = json.load(f, object_hook=date_hook)
for event in result["events"]:
print(f" {event['action']}: {event['time']} (类型: {type(event['time']).__name__})")输出:
代码示例
login: 2024-01-15 09:00:00 (类型: datetime)
logout: 2024-01-15 18:00:00 (类型: datetime)示例3:多格式数据导入器
代码示例
import json
from decimal import Decimal
class DataImporter:
"""多格式数据导入器"""
@staticmethod
def import_json(filepath, use_decimal=False):
"""导入JSON文件"""
kwargs = {}
if use_decimal:
kwargs['parse_float'] = Decimal
with open(filepath, "r", encoding="utf-8") as f:
return json.load(f, **kwargs)
@staticmethod
def import_jsonl(filepath):
"""导入JSONL文件(每行一个JSON对象)"""
results = []
with open(filepath, "r", encoding="utf-8") as f:
for line_num, line in enumerate(f, 1):
line = line.strip()
if line:
try:
results.append(json.loads(line))
except json.JSONDecodeError as e:
print(f"第{line_num}行解析失败: {e}")
return results
@staticmethod
def validate_schema(data, required_keys):
"""验证数据结构"""
missing = [k for k in required_keys if k not in data]
if missing:
raise ValueError(f"缺少必要字段: {missing}")
return True
# 使用示例
data = DataImporter.import_json("user.json")
print(f"导入数据: {data}")
# 验证结构
try:
DataImporter.validate_schema(data, ["name", "age", "email"])
except ValueError as e:
print(f"验证失败: {e}")输出:
代码示例
导入数据: {'name': '张三', 'age': 25, 'skills': ['Python', 'Java']}
验证失败: 缺少必要字段: ['email']实际应用场景
-
配置文件加载:读取 JSON 格式的应用配置文件
-
数据导入:从 JSON 文件批量导入数据到程序或数据库
-
日志分析:读取 JSON 格式的日志文件进行统计分析
注意事项
注意1:文件对象应以文本模式打开(
"r"),并指定encoding="utf-8",避免编码问题。
注意2:
json.load()会一次性读取整个文件内容。对于超大文件,考虑使用 JSONL 格式(每行一个 JSON 对象)逐行解析。
注意3:如果 JSON 文件格式错误,会引发
json.JSONDecodeError,应做好异常处理。
注意4:
json.load()读取后文件指针会移到末尾,如需再次读取需f.seek(0)重置。
提示:
json.load(f)比json.loads(f.read())更高效,因为前者直接从文件流解析,避免了中间字符串的内存分配。
相关方法对比
小结
-
json.load()从文件对象读取并解析 JSON 数据,比loads(f.read())更高效 -
参数与
loads()一致,支持object_hook、parse_float等自定义解析 -
读取文件时应使用
with语句和encoding="utf-8" -
超大 JSON 文件建议使用 JSONL 格式或
ijson库进行流式解析
练习题
练习1
编写一个函数 safe_json_load(filepath),处理文件不存在和 JSON 格式错误两种异常,返回 (data, error) 元组。
练习2
编写一个 JSONL 文件读取器,逐行解析 JSON,统计总行数、成功解析数和失败行号。
练习3
编写一个函数,使用 parse_float=Decimal 从文件读取 JSON,计算所有数值字段的总和并保持精度。
常见问题
json.load()和json.loads()有什么区别?
json.load()从文件对象读取JSON数据,而json.loads()从字符串读取。load()更高效,因为它直接从文件流解析,避免了先将整个文件读入内存字符串的开销。
如何处理超大JSON文件?
对于超大JSON文件,建议使用JSONL格式(每行一个JSON对象)逐行解析,或者使用ijson库进行流式解析,这样可以避免一次性加载整个文件到内存中。
object_hook参数的作用是什么?
object_hook是一个回调函数,在每个JSON对象解码后被调用。它可以用于自动转换特定格式的数据,如将ISO日期字符串转换为datetime对象。
读取JSON文件时为什么需要指定encoding="utf-8"?
指定encoding="utf-8"可以确保正确读取包含中文等非ASCII字符的JSON文件。在不同操作系统上,默认编码可能不同,显式指定utf-8可以避免编码问题。
本文涉及AI创作
内容由AI创作,请仔细甄别