Python JSON的深度解析:从基础到应用
Python JSON的深度解析:从基础到应用
flyfish
什么是JSON?
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。它基于一个子集的JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999。JSON采用完全独立于语言的文本格式,但也使用类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。这些特性使得JSON成为理想的数据交换语言。
Python中的json
库和Flask中的jsonify
-
Python
json
库:这是Python标准库的一部分,提供了将Python对象转换为JSON格式字符串(序列化)以及将JSON格式字符串转换回Python对象(反序列化)的功能。主要方法包括dumps()
用于序列化,loads()
用于反序列化。 -
Flask中的
jsonify
:这是Flask框架提供的一个便捷函数,用来生成JSON响应。它不仅将数据转换为JSON格式,还会设置HTTP响应的Content-Type为application/json
,非常适合构建API服务时返回JSON数据给客户端。
JSON的例子
{
"name": "张三",
"age": 30,
"is_student": false,
"courses": ["数学", "物理"],
"address": {
"city": "北京",
"zip_code": "100084"
}
}
如何组成JSON及解析
- 组成JSON:在Python中使用
json
库来创建JSON字符串非常简单。例如:
import json
data = {
'name': '李四',
'age': 25,
'is_student': True,
'courses': ['化学', '生物'],
'address': {
'city': '上海',
'zip_code': '200000'
}
}
json_str = json.dumps(data, ensure_ascii=False)
print(json_str)
- 解析JSON:同样地,可以使用
json.loads()
来解析JSON字符串回到Python对象:
parsed_data = json.loads(json_str)
print(parsed_data)
使用Python的json
库来解析
import json
# 假设这是从网络获取的复杂JSON字符串
json_str = '''
{
"school_name": "实验中学",
"location": {
"city": "济南",
"address": "济南经十路"
},
"students": [
{"name": "张三", "age": 15, "grades": {"数学": 93, "英语": 88}},
{"name": "李四", "age": 14, "grades": {"数学": 97, "英语": 92}},
{"name": "王五", "age": 16, "grades": {"数学": 90, "英语": 85}}
]
}
'''
# 解析JSON字符串
data = json.loads(json_str)
# 打印学校名称
print("学校名称:", data['school_name'])
# 遍历并打印学生信息
for student in data['students']:
print(f"姓名: {student['name']}, 年龄: {student['age']}")
for subject, grade in student['grades'].items():
print(f" {subject}: {grade}")
# 修改某个学生的成绩并重新转换为JSON字符串
data['students'][0]['grades']['数学'] = 95
updated_json_str = json.dumps(data, ensure_ascii=False, indent=4)
print("\n更新后的JSON字符串:")
print(updated_json_str)
常用函数
-
json.dump(obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)
- 将Python对象写入文件(或类似文件的对象)。
ensure_ascii
: 如果为False
, 则允许非ASCII字符直接输出而不是转义序列。indent
: 控制缩进以美化输出。
-
json.dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)
- 将Python对象转换为JSON格式的字符串。
-
json.load(fp, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)
- 从文件(或类似文件的对象)读取JSON数据并解码成Python对象。
-
json.loads(s, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)
- 将JSON格式的字符串解码成Python对象。
显示汉字
在处理包含中文字符的JSON时,确保ensure_ascii
参数设置为False
非常重要。这样,Python不会将非ASCII字符转换为Unicode转义序列,而是直接输出原始字符。例如:
data = {
'name': '李华',
'message': '你好,世界!'
}
# 确保ensure_ascii=False来正确显示中文
json_str = json.dumps(data, ensure_ascii=False)
print(json_str)
这将输出实际的中文字符而非其Unicode编码形式。同样,在使用json.dump()
写入文件时也应设置ensure_ascii=False
,以确保文件中保存的是原始中文字符。
在Flask中使用jsonify
来构建返回JSON格式数据的API
jsonify
是Flask提供的一个便捷函数,用于生成JSON响应,并自动设置HTTP响应的Content-Type为application/json
。创建一个简单的Flask应用,该应用有一个API端点,它返回一些用户信息作为JSON格式的数据。
安装Flask
首先,确保你已经安装了Flask。如果还没有安装,可以使用pip来安装:
pip install Flask
创建Flask应用
下面是一个完整的示例代码,展示了如何使用jsonify
函数来返回JSON数据。
from flask import Flask, jsonify, request
app = Flask(__name__)
# 模拟的用户数据
users = [
{"id": 1, "name": "张三", "age": 30},
{"id": 2, "name": "李四", "age": 25},
{"id": 3, "name": "王五", "age": 28}
]
# 获取所有用户的API
@app.route('/api/users', methods=['GET'])
def get_users():
return jsonify(users)
# 根据ID获取单个用户的API
@app.route('/api/users/<int:user_id>', methods=['GET'])
def get_user(user_id):
user = next((user for user in users if user["id"] == user_id), None)
if user is not None:
return jsonify(user)
else:
return jsonify({"error": "User not found"}), 404
# 添加新用户的API
@app.route('/api/users', methods=['POST'])
def add_user():
new_user = request.get_json()
if not new_user or 'name' not in new_user or 'age' not in new_user:
return jsonify({"error": "Invalid input"}), 400
# 生成一个新的用户ID
new_user['id'] = max(user['id'] for user in users) + 1
users.append(new_user)
return jsonify(new_user), 201
# 更新用户的API
@app.route('/api/users/<int:user_id>', methods=['PUT'])
def update_user(user_id):
update_data = request.get_json()
user = next((user for user in users if user["id"] == user_id), None)
if user is None:
return jsonify({"error": "User not found"}), 404
user.update(update_data)
return jsonify(user)
# 删除用户的API
@app.route('/api/users/<int:user_id>', methods=['DELETE'])
def delete_user(user_id):
global users
initial_length = len(users)
users = [user for user in users if user["id"] != user_id]
if len(users) < initial_length:
return jsonify({"message": "User deleted"}), 200
else:
return jsonify({"error": "User not found"}), 404
if __name__ == '__main__':
app.run(debug=True)
运行应用
保存上述代码到一个文件(例如app.py
),然后在终端中运行:
python app.py
默认情况下,Flask应用会在http://127.0.0.1:5000/
上运行。
测试API
你可以使用curl
命令或者Postman等工具来测试这些API端点。以下是一些示例请求:
-
获取所有用户:
curl -X GET http://127.0.0.1:5000/api/users
-
根据ID获取单个用户:
curl -X GET http://127.0.0.1:5000/api/users/1
-
添加新用户:
curl -X POST -H "Content-Type: application/json" -d '{"name": "赵六", "age": 22}' http://127.0.0.1:5000/api/users
-
更新用户信息:
curl -X PUT -H "Content-Type: application/json" -d '{"age": 31}' http://127.0.0.1:5000/api/users/1
-
删除用户:
curl -X DELETE http://127.0.0.1:5000/api/users/1
Python 原始类型与 JSON 类型之间的对应关系
当客户端(如浏览器、移动应用)需要从服务器获取数据时,通常会请求 JSON 格式的数据。服务器端将 Python 对象序列化为 JSON 字符串,并发送给客户端,需要将 Python 数据结构(如字典、列表等)转换为 JSON 字符串。
在 Python 中,json
模块提供了 dumps()
和 loads()
方法来进行序列化(Python 到 JSON)和反序列化(JSON 到 Python)。
Python 类型 | JSON 类型 | 备注 |
---|---|---|
dict | object | 字典会被转换为 JSON 对象 |
list , tuple | array | 列表和元组都会被转换为 JSON 数组 |
str | string | 字符串保持不变 |
int , float | number | 整数和浮点数都被转换为 JSON 数字 |
True | true | Python 的布尔值 True 转换为 JSON 的 true |
False | false | Python 的布尔值 False 转换为 JSON 的 false |
None | null | Python 的 None 转换为 JSON 的 null |
示例代码
以下是一些具体的示例,展示了如何将 Python 数据结构转换为 JSON 字符串:
import json
# Python 数据结构
data = {
"name": "张三",
"age": 30,
"is_student": False,
"courses": ["数学", "物理"],
"address": {
"city": "北京",
"zip_code": "100084"
},
"scores": {"数学": 93, "英语": 88},
"active": True,
"metadata": None
}
# 将 Python 数据结构转换为 JSON 字符串
json_str = json.dumps(data, ensure_ascii=False, indent=4)
print(json_str)
# 输出:
# {
# "name": "张三",
# "age": 30,
# "is_student": false,
# "courses": [
# "数学",
# "物理"
# ],
# "address": {
# "city": "北京",
# "zip_code": "100084"
# },
# "scores": {
# "数学": 93,
# "英语": 88
# },
# "active": true,
# "metadata": null
# }
注意事项
-
ensure_ascii=False
:如果你的数据包含非ASCII字符(如中文),确保设置ensure_ascii=False
,以避免这些字符被转义为 Unicode 编码形式。 -
indent
参数:用于美化输出,指定缩进级别。
自定义序列化:如果遇到无法直接序列化的对象(如自定义类实例),可以使用 default
参数提供一个函数来处理这些情况。
def custom_serializer(obj):
if isinstance(obj, datetime.datetime):
return obj.isoformat()
raise TypeError(f"Type {type(obj)} not serializable")
json_str = json.dumps(data, default=custom_serializer)