JSON 在 Python 中的使用

JSON 与 Python

Python 内置了 json 模块,可以轻松地在 JSON 数据和 Python 对象之间进行转换。JSON 对象对应于 Python 字典,JSON 数组对应于 Python 列表。

{"{}"}

json.loads()

将 JSON 字符串转换为 Python 对象

" "

json.dumps()

将 Python 对象转换为 JSON 字符串

📁

文件操作

读写 JSON 文件

🔧

高级功能

自定义序列化、编码处理

import json
首先需要导入 Python 的 json 模块

JSON 解析 - json.loads()

json.loads() 方法用于将 JSON 字符串解析为 Python 对象。

import json

# JSON 字符串
json_string = '{"name": "张三", "age": 30, "is_student": false}'

# 解析为 Python 字典
data = json.loads(json_string)

# 访问数据
print(data['name']) # 张三
print(data['age']) # 30
print(data['is_student']) # False
print(type(data)) # <class 'dict'>

JSON 与 Python 数据类型映射

JSON 数据类型 Python 数据类型 示例
对象 (object) 字典 (dict) {"name": "张三"}{"name": "张三"}
数组 (array) 列表 (list) ["apple", "banana"]["apple", "banana"]
字符串 (string) 字符串 (str) "hello""hello"
数字 (number) 整数 (int) 或 浮点数 (float) 4242, 3.143.14
布尔值 (boolean) 布尔值 (bool) trueTrue, falseFalse
空值 (null) None nullNone

处理复杂 JSON 数据

import json

# 复杂的 JSON 字符串
complex_json = '''{
"users": [
{
"id": 1,
"name": "张三",
"hobbies": ["阅读", "游泳"],
"profile": {
"age": 30,
"city": "北京"
}
},
{
"id": 2,
"name": "李四",
"hobbies": ["音乐", "旅行"],
"profile": {
"age": 25,
"city": "上海"
}
}
]
}'''

# 解析 JSON
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

# Python 字典
data = {
"name": "张三",
"age": 30,
"is_student": False,
"hobbies": ["阅读", "游泳"]
}

# 序列化为 JSON 字符串
json_string = json.dumps(data)
print(json_string)
# '{"name": "张三", "age": 30, "is_student": false, "hobbies": ["阅读", "游泳"]}'

格式化输出

使用 indent 参数可以美化 JSON 输出。

import json

data = {
"name": "张三",
"age": 30,
"address": {
"city": "北京",
"country": "中国"
}
}

# 缩进 4 个空格
formatted_json = json.dumps(data, indent=4)
print(formatted_json)
# {
# "name": "张三",
# "age": 30,
# "address": {
# "city": "北京",
# "country": "中国"
# }
# }

处理中文

默认情况下,json.dumps() 会将中文字符转换为 Unicode 转义序列,使用 ensure_ascii=False 可以保留中文字符。

import json

data = {
"name": "张三",
"city": "北京"
}

# 默认输出(中文被转义)
default_output = json.dumps(data)
print(default_output) # {"name": "\u5f20\u4e09", "city": "\u5317\u4eac"}

# 保留中文字符
chinese_output = json.dumps(data, ensure_ascii=False)
print(chinese_output) # {"name": "张三", "city": "北京"}

排序键

使用 sort_keys 参数可以对字典键进行排序。

import json

data = {
"name": "张三",
"age": 30,
"city": "北京"
}

# 按键排序
sorted_json = json.dumps(data, sort_keys=True, indent=2)
print(sorted_json)
# {
# "age": 30,
# "city": "北京",
# "name": "张三"
# }

JSON 文件操作

Python 提供了直接读写 JSON 文件的方法。

读取 JSON 文件

import json

# 从文件读取 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": ["阅读", "游泳"]
}

# 写入 JSON 文件
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 {}

# 写入 JSON 文件
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):
# 处理 datetime 对象
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)
# {"timestamp": "2023-10-05T00:00:00", "message": "Hello World"}

自定义解析

可以使用 object_hook 参数在解析时转换对象。

import json
from datetime import datetime

def datetime_parser(dct):
for key, value in dct.items():
# 将 ISO 格式的字符串转换为 datetime 对象
if isinstance(value, str):
try:
dct[key] = datetime.fromisoformat(value)
except ValueError:
pass
return dct

# JSON 字符串包含日期
json_string = '{"created_at": "2023-10-05T14:30:00", "name": "张三"}'

# 使用自定义解析器
data = json.loads(json_string, object_hook=datetime_parser)
print(data['created_at']) # 2023-10-05 14:30:00
print(type(data['created_at'])) # <class 'datetime.datetime'>

处理复杂对象

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) # {"name": "张三", "age": 30}

# 从 JSON 恢复对象
loaded_dict = json.loads(json_string)
loaded_user = User.from_dict(loaded_dict)
print(type(loaded_user)) # <class '__main__.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():
# 返回 JSON 响应
return jsonify({"users": users})

@app.route('/api/users', methods=['POST'])
def create_user():
# 从请求中获取 JSON 数据
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

# 从 API 获取 JSON 数据
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() # 直接解析 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 字符串之间的转换。

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

# 有效的 JSON
result1 = safe_json_loads('{"name": "张三"}')
print(result1) # {'name': '张三'}

# 无效的 JSON
result2 = safe_json_loads('{name: "张三"}') # 缺少引号
print(result2) # None

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 库可以获得更好的性能(但可能牺牲一些功能)
  • 只序列化需要的字段,减少数据量
  • 对于频繁操作的数据,考虑缓存解析结果