第85集:JSON文件操作
学习目标
- 理解JSON数据格式的基本概念
- 掌握json模块的使用方法
- 学会读取和写入JSON文件
- 掌握JSON数据的序列化和反序列化
- 学会处理JSON文件中的常见问题
一、JSON概述
1.1 什么是JSON
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。它基于JavaScript的一个子集,但是完全独立于语言。
1.2 JSON的特点
- 轻量级:数据格式简洁,易于传输
- 可读性:人类可读,易于理解和调试
- 跨语言:支持多种编程语言
- 结构化:支持嵌套的数据结构
1.3 JSON数据类型
| JSON类型 | Python类型 | 示例 |
|---|---|---|
| 对象(object) | dict | {"name": "张三", "age": 25} |
| 数组(array) | list | [1, 2, 3, 4, 5] |
| 字符串(string) | str | "Hello, World!" |
| 数字(number) | int/float | 42, 3.14 |
| 布尔值(boolean) | bool | true, false |
| null | None | null |
1.4 JSON格式示例
{
"name": "张三",
"age": 25,
"is_student": true,
"hobbies": ["读书", "游泳", "编程"],
"address": {
"city": "北京",
"district": "朝阳区"
},
"scores": {
"math": 95,
"english": 88,
"physics": 92
}
}二、json模块简介
2.1 导入json模块
import json2.2 json模块的主要函数
- **json.dumps()**:将Python对象转换为JSON字符串
- **json.dump()**:将Python对象写入JSON文件
- **json.loads()**:将JSON字符串转换为Python对象
- **json.load()**:从JSON文件读取并转换为Python对象
三、JSON序列化
3.1 使用dumps()转换为JSON字符串
import json
data = {
"name": "张三",
"age": 25,
"is_student": True
}
json_str = json.dumps(data)
print(json_str)
# 输出:{"name": "\u5f20\u4e09", "age": 25, "is_student": true}3.2 使用ensure_ascii参数
默认情况下,非ASCII字符会被转义。使用ensure_ascii=False可以保留原始字符。
import json
data = {"name": "张三", "age": 25}
# 默认:转义非ASCII字符
json_str1 = json.dumps(data)
print(json_str1)
# 输出:{"name": "\u5f20\u4e09", "age": 25}
# 保留原始字符
json_str2 = json.dumps(data, ensure_ascii=False)
print(json_str2)
# 输出:{"name": "张三", "age": 25}3.3 使用indent参数格式化输出
使用indent参数可以美化JSON输出。
import json
data = {
"name": "张三",
"age": 25,
"hobbies": ["读书", "游泳"]
}
json_str = json.dumps(data, indent=2, ensure_ascii=False)
print(json_str)3.4 使用sort_keys参数排序键
使用sort_keys=True可以按键名排序。
import json
data = {
"name": "张三",
"age": 25,
"city": "北京"
}
json_str = json.dumps(data, sort_keys=True, indent=2, ensure_ascii=False)
print(json_str)四、JSON反序列化
4.1 使用loads()转换为Python对象
import json
json_str = '{"name": "张三", "age": 25, "is_student": true}'
data = json.loads(json_str)
print(data)
# 输出:{'name': '张三', 'age': 25, 'is_student': True}4.2 访问JSON数据
import json
json_str = '{"name": "张三", "age": 25, "hobbies": ["读书", "游泳"]}'
data = json.loads(json_str)
print(data["name"])
print(data["age"])
print(data["hobbies"][0])五、JSON文件操作
5.1 写入JSON文件
使用json.dump()函数将Python对象写入JSON文件。
import json
data = {
"name": "张三",
"age": 25,
"is_student": True,
"hobbies": ["读书", "游泳", "编程"]
}
with open('data.json', 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)5.2 读取JSON文件
使用json.load()函数从JSON文件读取数据。
import json
with open('data.json', 'r', encoding='utf-8') as f:
data = json.load(f)
print(data)六、JSON数据处理
6.1 处理嵌套JSON数据
import json
json_str = '''
{
"name": "张三",
"address": {
"city": "北京",
"district": "朝阳区"
},
"scores": {
"math": 95,
"english": 88
}
}
'''
data = json.loads(json_str)
print(data["address"]["city"])
print(data["scores"]["math"])6.2 处理JSON数组
import json
json_str = '''
[
{"name": "张三", "age": 25},
{"name": "李四", "age": 30},
{"name": "王五", "age": 28}
]
'''
data = json.loads(json_str)
for person in data:
print(f"{person['name']}: {person['age']}岁")6.3 筛选JSON数据
import json
json_str = '''
[
{"name": "张三", "age": 25, "score": 95},
{"name": "李四", "age": 30, "score": 88},
{"name": "王五", "age": 28, "score": 92}
]
'''
data = json.loads(json_str)
filtered = [person for person in data if person["score"] > 90]
print(filtered)6.4 修改JSON数据
import json
json_str = '{"name": "张三", "age": 25}'
data = json.loads(json_str)
data["age"] = 26
data["city"] = "北京"
new_json_str = json.dumps(data, ensure_ascii=False, indent=2)
print(new_json_str)七、JSON与数据结构转换
7.1 字典转换为JSON
import json
data = {
"name": "张三",
"age": 25,
"city": "北京"
}
json_str = json.dumps(data, ensure_ascii=False, indent=2)
print(json_str)7.2 列表转换为JSON
import json
data = [1, 2, 3, 4, 5]
json_str = json.dumps(data, indent=2)
print(json_str)7.3 嵌套结构转换为JSON
import json
data = {
"students": [
{"name": "张三", "age": 25},
{"name": "李四", "age": 30}
],
"teacher": {
"name": "王老师",
"subject": "数学"
}
}
json_str = json.dumps(data, ensure_ascii=False, indent=2)
print(json_str)八、JSON文件常见问题
8.1 编码问题
import json
# 写入JSON文件时指定编码
data = {"name": "张三", "age": 25}
with open('data.json', 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
# 读取JSON文件时指定编码
with open('data.json', 'r', encoding='utf-8') as f:
data = json.load(f)
print(data)8.2 处理不支持的Python类型
Python的某些类型(如datetime、set等)不能直接序列化为JSON。
import json
from datetime import datetime
# 错误示例:datetime不能直接序列化
data = {"time": datetime.now()}
try:
json_str = json.dumps(data)
except TypeError as e:
print(f"错误:{e}")
# 解决方法:转换为字符串
data = {"time": datetime.now().isoformat()}
json_str = json.dumps(data)
print(json_str)8.3 处理JSON解析错误
import json
# 错误的JSON字符串
invalid_json = '{"name": "张三", "age": 25'
try:
data = json.loads(invalid_json)
except json.JSONDecodeError as e:
print(f"JSON解析错误:{e}")8.4 处理大JSON文件
对于大JSON文件,可以使用ijson库进行流式处理。
# 需要安装:pip install ijson
import ijson
with open('large_file.json', 'rb') as f:
for item in ijson.items(f, 'item'):
process(item)九、JSON高级操作
9.1 自定义JSON编码器
import json
from datetime import datetime
class DateTimeEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime):
return obj.isoformat()
return super().default(obj)
data = {
"name": "张三",
"time": datetime.now()
}
json_str = json.dumps(data, cls=DateTimeEncoder, ensure_ascii=False, indent=2)
print(json_str)9.2 自定义JSON解码器
import json
from datetime import datetime
def datetime_decoder(obj):
if 'time' in obj:
obj['time'] = datetime.fromisoformat(obj['time'])
return obj
json_str = '{"name": "张三", "time": "2024-01-01T12:00:00"}'
data = json.loads(json_str, object_hook=datetime_decoder)
print(data)9.3 合并JSON数据
import json
json1 = '{"name": "张三", "age": 25}'
json2 = '{"city": "北京", "score": 95}'
data1 = json.loads(json1)
data2 = json.loads(json2)
merged = {**data1, **data2}
json_str = json.dumps(merged, ensure_ascii=False, indent=2)
print(json_str)9.4 JSON数据验证
import json
def validate_json(json_str):
try:
data = json.loads(json_str)
return True, data
except json.JSONDecodeError as e:
return False, str(e)
json_str = '{"name": "张三", "age": 25}'
is_valid, result = validate_json(json_str)
print(f"是否有效:{is_valid}")
print(f"结果:{result}")十、最佳实践
10.1 使用with语句
# 推荐
with open('data.json', 'r', encoding='utf-8') as f:
data = json.load(f)
# 不推荐
f = open('data.json', 'r', encoding='utf-8')
data = json.load(f)
f.close()10.2 指定编码方式
# 推荐
with open('data.json', 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False)
# 不推荐
with open('data.json', 'w') as f:
json.dump(data, f)10.3 格式化JSON输出
# 推荐:使用indent参数
json_str = json.dumps(data, indent=2, ensure_ascii=False)
# 不推荐:不使用indent参数
json_str = json.dumps(data)10.4 异常处理
import json
try:
with open('data.json', 'r', encoding='utf-8') as f:
data = json.load(f)
except FileNotFoundError:
print('文件不存在')
except json.JSONDecodeError:
print('JSON格式错误')
except Exception as e:
print(f'发生错误:{e}')十一、总结
本集学习了JSON文件操作的知识:
- JSON数据格式的基本概念和数据类型
- json模块的使用方法
- JSON数据的序列化和反序列化
- JSON文件的读取和写入
- JSON数据的处理和转换
- JSON文件常见问题和最佳实践
JSON是一种广泛使用的数据交换格式,在Web开发、API接口、配置文件等场景中非常重要。下一集我们将学习XML文件操作。
十二、练习题
- 创建一个JSON文件,包含学生信息(姓名、年龄、成绩、爱好),然后读取并显示。
- 编写一个函数,将字典列表转换为JSON字符串。
- 实现一个函数,筛选出成绩大于90分的学生。
- 编写一个程序,合并两个JSON文件的数据。
- 实现一个自定义JSON编码器,处理datetime对象。
- 编写一个函数,验证JSON字符串的有效性。
- 实现一个程序,统计JSON数组中每个城市的平均成绩。
- 编写一个程序,将CSV文件转换为JSON文件。