JSON 在 Python 中的使用
JSON 与 Python
Python 内置了 json 模块,可以轻松地在 JSON 数据和 Python 对象之间进行转换。JSON 对象对应于 Python 字典,JSON 数组对应于 Python 列表。
{"{}"}
json.loads()
将 JSON 字符串转换为 Python 对象
" "
json.dumps()
将 Python 对象转换为 JSON 字符串
import json
首先需要导入 Python 的 json 模块
JSON 解析 - json.loads()
json.loads() 方法用于将 JSON 字符串解析为 Python 对象。
import json
json_string = '{"name": "张三", "age": 30, "is_student": false}'
data = json.loads(json_string)
print(data['name'])
print(data['age'])
print(data['is_student'])
print(type(data))
JSON 与 Python 数据类型映射
| JSON 数据类型 |
Python 数据类型 |
示例 |
| 对象 (object) |
字典 (dict) |
{"name": "张三"} → {"name": "张三"} |
| 数组 (array) |
列表 (list) |
["apple", "banana"] → ["apple", "banana"] |
| 字符串 (string) |
字符串 (str) |
"hello" → "hello" |
| 数字 (number) |
整数 (int) 或 浮点数 (float) |
42 → 42, 3.14 → 3.14 |
| 布尔值 (boolean) |
布尔值 (bool) |
true → True, false → False |
| 空值 (null) |
None |
null → None |
处理复杂 JSON 数据
import json
complex_json = '''{
"users": [
{
"id": 1,
"name": "张三",
"hobbies": ["阅读", "游泳"],
"profile": {
"age": 30,
"city": "北京"
}
},
{
"id": 2,
"name": "李四",
"hobbies": ["音乐", "旅行"],
"profile": {
"age": 25,
"city": "上海"
}
}
]
}'''
data = json.loads(complex_json)
print(data['users'][0]['name'])
print(data['users'][0]['profile']['city'])
print(data['users'][1]['hobbies'][0])
提示: 使用 json.loads() 时,如果 JSON 格式不正确,会抛出 json.JSONDecodeError 异常,建议使用 try-except 进行处理。
JSON 序列化 - json.dumps()
json.dumps() 方法用于将 Python 对象序列化为 JSON 字符串。
import json
data = {
"name": "张三",
"age": 30,
"is_student": False,
"hobbies": ["阅读", "游泳"]
}
json_string = json.dumps(data)
print(json_string)
格式化输出
使用 indent 参数可以美化 JSON 输出。
import json
data = {
"name": "张三",
"age": 30,
"address": {
"city": "北京",
"country": "中国"
}
}
formatted_json = json.dumps(data, indent=4)
print(formatted_json)
处理中文
默认情况下,json.dumps() 会将中文字符转换为 Unicode 转义序列,使用 ensure_ascii=False 可以保留中文字符。
import json
data = {
"name": "张三",
"city": "北京"
}
default_output = json.dumps(data)
print(default_output)
chinese_output = json.dumps(data, ensure_ascii=False)
print(chinese_output)
排序键
使用 sort_keys 参数可以对字典键进行排序。
import json
data = {
"name": "张三",
"age": 30,
"city": "北京"
}
sorted_json = json.dumps(data, sort_keys=True, indent=2)
print(sorted_json)
JSON 文件操作
Python 提供了直接读写 JSON 文件的方法。
读取 JSON 文件
import json
with open('data.json', 'r', encoding='utf-8') as file:
data = json.load(file)
print(data)
写入 JSON 文件
import json
data = {
"name": "张三",
"age": 30,
"hobbies": ["阅读", "游泳"]
}
with open('output.json', 'w', encoding='utf-8') as file:
json.dump(data, file, ensure_ascii=False, indent=4)
print("数据已保存到 output.json")
完整的文件操作示例
import json
import os
def read_json_file(filename):
if os.path.exists(filename):
with open(filename, 'r', encoding='utf-8') as file:
return json.load(file)
return {}
def write_json_file(filename, data):
with open(filename, 'w', encoding='utf-8') as file:
json.dump(data, file, ensure_ascii=False, indent=2)
user_data = {
"users": [
{"id": 1, "name": "张三"},
{"id": 2, "name": "李四"}
]
}
write_json_file('users.json', user_data)
loaded_data = read_json_file('users.json')
print("加载的数据:", loaded_data)
高级功能
自定义序列化
可以通过继承 json.JSONEncoder 类来自定义序列化行为。
import json
from datetime import datetime
class CustomEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, datetime):
return obj.isoformat()
elif isinstance(obj, User):
return {'name': obj.name, 'age': obj.age}
return super().default(obj)
data = {
"timestamp": datetime(2023, 10, 5),
"message": "Hello World"
}
json_string = json.dumps(data, cls=CustomEncoder)
print(json_string)
自定义解析
可以使用 object_hook 参数在解析时转换对象。
import json
from datetime import datetime
def datetime_parser(dct):
for key, value in dct.items():
if isinstance(value, str):
try:
dct[key] = datetime.fromisoformat(value)
except ValueError:
pass
return dct
json_string = '{"created_at": "2023-10-05T14:30:00", "name": "张三"}'
data = json.loads(json_string, object_hook=datetime_parser)
print(data['created_at'])
print(type(data['created_at']))
处理复杂对象
import json
class User:
def __init__(self, name, age):
self.name = name
self.age = age
def to_dict(self):
return {'name': self.name, 'age': self.age}
@classmethod
def from_dict(cls, data):
return cls(data['name'], data['age'])
user = User("张三", 30)
user_dict = user.to_dict()
json_string = json.dumps(user_dict, ensure_ascii=False)
print(json_string)
loaded_dict = json.loads(json_string)
loaded_user = User.from_dict(loaded_dict)
print(type(loaded_user))
print(loaded_user.name)
实际应用场景
1. Web API 开发
import json
from flask import Flask, request, jsonify
app = Flask(__name__)
users = [
{"id": 1, "name": "张三", "email": "zhangsan@example.com"},
{"id": 2, "name": "李四", "email": "lisi@example.com"}
]
@app.route('/api/users', methods=['GET'])
def get_users():
return jsonify({"users": users})
@app.route('/api/users', methods=['POST'])
def create_user():
user_data = request.json
new_user = {
"id": len(users) + 1,
"name": user_data['name'],
"email": user_data['email']
}
users.append(new_user)
return jsonify(new_user), 201
if __name__ == '__main__':
app.run(debug=True)
2. 配置文件管理
import json
import os
class Config:
def __init__(self, config_file='config.json'):
self.config_file = config_file
self.data = self.load_config()
def load_config(self):
if not os.path.exists(self.config_file):
default_config = {
"database": {
"host": "localhost",
"port": 5432,
"name": "myapp"
},
"app": {
"debug": True,
"secret_key": "your-secret-key"
}
}
self.save_config(default_config)
return default_config
with open(self.config_file, 'r') as file:
return json.load(file)
def save_config(self, data=None):
if data is None:
data = self.data
with open(self.config_file, 'w') as file:
json.dump(data, file, indent=2)
def get(self, key, default=None):
return self.data.get(key, default)
def set(self, key, value):
self.data[key] = value
self.save_config()
config = Config()
print(config.get("database"))
config.set("app.debug", False)
3. 数据交换格式
import json
import requests
def fetch_weather_data(city):
url = f"https://api.weather.com/data/{city}"
try:
response = requests.get(url)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f"获取天气数据失败: {e}")
return None
def process_weather_data(data):
if data and 'weather' in data:
weather = data['weather']
temperature = weather.get('temperature', '未知')
condition = weather.get('condition', '未知')
return {
'temperature': temperature,
'condition': condition,
'description': f"当前温度: {temperature}°C, 天气: {condition}"
}
return {'error': '无法获取天气数据'}
weather_data = fetch_weather_data("beijing")
if weather_data:
processed_data = process_weather_data(weather_data)
print(json.dumps(processed_data, ensure_ascii=False, indent=2))
交互式演示
在下面的演示区域中,您可以尝试 Python 对象与 JSON 字符串之间的转换。
注意事项
1. 错误处理
始终处理 JSON 解析可能出现的异常:
import json
def safe_json_loads(json_string):
try:
return json.loads(json_string)
except json.JSONDecodeError as e:
print(f"JSON 解析错误: {e}")
return None
result1 = safe_json_loads('{"name": "张三"}')
print(result1)
result2 = safe_json_loads('{name: "张三"}')
print(result2)
2. 编码问题
处理文件时注意编码问题:
with open('data.json', 'r', encoding='utf-8') as file:
data = json.load(file)
with open('output.json', 'w', encoding='utf-8') as file:
json.dump(data, file, ensure_ascii=False, indent=2)
3. 性能优化
处理大型 JSON 数据时的优化建议:
- 对于非常大的 JSON 文件,考虑使用
ijson 库进行流式解析
- 使用
ujson 库可以获得更好的性能(但可能牺牲一些功能)
- 只序列化需要的字段,减少数据量
- 对于频繁操作的数据,考虑缓存解析结果