Files
PythonLearn/05_web基础/5_4_JSON数据交换/README.md
T

257 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 第5-4课:JSON数据交换
## 一、本课目标
完成本课后,你能够:
1. 说明JSON是什么以及为什么Web接口经常使用JSON;
2. 区分Python对象、JSON文本和网络中的字节;
3. 掌握JSON的六类基本值;
4. 使用`json.dumps()`完成序列化;
5. 使用`json.loads()`完成反序列化;
6. 识别常见JSON格式错误和不支持的数据类型;
7. 看懂HTTP请求体或响应体中的JSON。
## 二、前置知识
- Python字典、列表、字符串、数字、布尔值和`None`;
- 已理解HTTP请求体、响应体和`Content-Type`;
- 本课不重复讲解Python容器和异常处理语法。
## 三、为什么需要数据交换格式
客户端和服务器可能使用不同语言。例如浏览器使用JavaScript,后端使用Python。Python字典只能直接存在于Python程序内,不能原样作为跨语言约定。
双方需要一种共同格式:
```text
Python字典 → JSON文本 → HTTP传输 → JSON文本 → JavaScript对象
```
JavaScript对象表示法(JavaScript Object Notation,JSON)是一种轻量的文本数据格式。它由字符组成,与具体编程语言无关,因此非常适合Web接口交换结构化数据。
## 四、不要混淆三个层次
下面三项表示相近内容,但类型不同:
```python
# Python字典:程序可以按键读取和修改
book = {"id": 1, "available": True}
# JSON文本:本质是一个Python字符串
json_text = '{"id": 1, "available": true}'
# UTF-8字节:真正写入网络连接的数据形式之一
json_bytes = json_text.encode("utf-8")
```
特别注意:
- Python使用`True`和`None`;
- JSON使用`true`和`null`;
- Python字典显示时可能使用单引号;
- JSON属性名和字符串必须使用双引号。
因此,`str(book)`不是可靠的JSON生成方式。
## 五、JSON支持哪些值
| JSON类型 | JSON示例 | 转成Python后的类型 |
|---|---|---|
| object | `{"title": "Python"}` | `dict` |
| array | `["Python", "Web"]` | `list` |
| string | `"Python"` | `str` |
| number | `59.9` | `int`或`float` |
| boolean | `true`、`false` | `True`、`False` |
| null | `null` | `None` |
JSON没有元组、集合、日期时间、`Decimal`和自定义类等专用类型。发送这些值之前,需要先决定明确的表示形式。
例如日期时间通常转换成字符串:
```json
{"created_at": "2026-08-20T10:30:00+08:00"}
```
这只是常见约定,客户端和服务器仍需在接口文档中统一格式与时区。
## 六、阅读一段JSON
```json
{
"id": 1,
"title": "Python Web基础",
"price": 59.9,
"available": true,
"tags": ["Python", "Web"],
"description": null
}
```
从外向内阅读:
1. 最外层花括号表示一个object;
2. object中包含六组“属性名和值”;
3. `tags`的值是array;
4. array中有两个string;
5. `description`当前没有值,因此使用`null`。
JSON不允许在最后一个属性后留下多余逗号,也不支持Python风格的`# 注释`。
## 七、序列化
序列化(Serialization)是把程序中的对象转换成便于保存或传输的格式。本课是把Python对象转换为JSON文本:
```python
json_text = json.dumps(book, ensure_ascii=False, indent=2)
```
参数含义:
- `book`:需要转换的Python对象;
- `ensure_ascii=False`:中文直接保留,不显示成Unicode转义;
- `indent=2`:每层缩进两个空格,便于人阅读。
格式化缩进会增加数据大小,生产接口是否缩进由项目性能和可读性要求决定。
## 八、反序列化
反序列化(Deserialization)是把JSON文本还原为Python对象:
```python
request_body = '{"title": "HTTP实践", "price": 49.0}'
request_data = json.loads(request_body)
print(request_data["title"])
```
`json.loads()`中的字母`s`可以帮助记忆为“读取字符串”。解析成功只说明JSON语法正确,不表示字段满足业务规则。例如`{"title": ""}`是合法JSON,但空书名可能不符合业务要求。
## 九、JSON与HTTP怎样配合
客户端提交JSON时,应声明请求体格式:
```http
POST /books HTTP/1.1
Content-Type: application/json; charset=utf-8
{"title": "Python入门"}
```
服务器返回JSON时,也应声明响应体格式:
```http
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
{"id": 1, "title": "Python入门"}
```
`Content-Type`告诉接收方应按照什么格式解释正文。如果正文是JSON却声明为`text/plain`,有些工具仍能显示,但自动处理、文档和客户端代码可能出现问题。
## 十、完整示例
标准示例位于`json_rest_example.py`。文件名保留了创建阶段的名称,但本课示例只负责JSON转换,不讲RESTful API;RESTful将在下一课独立学习。
示例包含:
- 一个包含六种常见值的图书字典;
- Python对象转JSON文本;
- 保留中文并格式化缩进;
- JSON请求体转Python字典;
- 从解析结果中读取书名。
## 十一、运行方法
```powershell
cd D:\Code\Python\05_web基础\5_4_JSON数据交换
python json_rest_example.py
```
## 十二、预期结果
```text
JSON响应:
{
"id": 1,
"title": "Python Web基础",
"price": 59.9,
"available": true,
"tags": [
"Python",
"Web"
],
"description": null
}
请求中的书名:HTTP实践
```
如果看到`true`和`null`,说明输出是JSON写法,不是Python字典的直接显示结果。
## 十三、代码执行顺序
1. Python导入标准库`json`;
2. 程序从入口调用`main()`;
3. `serialize_book()`创建图书字典;
4. `json.dumps()`返回JSON字符串;
5. `print()`把JSON字符串显示到终端;
6. `deserialize_request()`接收一段JSON请求体;
7. `json.loads()`返回Python字典;
8. 程序读取字典中的`title`并输出。
## 十四、动手观察
建议复制示例后依次做以下小实验,每次只改一处:
1. 删除`ensure_ascii=False`,观察中文显示方式;
2. 把`indent=2`改为`indent=4`,观察缩进;
3. 在字典中增加`"stock": 10`,观察number;
4. 把请求体中的双引号改成单引号,观察解析错误;
5. 在JSON最后一个属性后增加逗号,观察解析错误。
实验结束后恢复标准示例,不要把故意制造的错误保留在示例文件中。
## 十五、常见错误
### 15.1 把Python字典文本当成JSON
`{'available': True}`是Python显示形式,不是合法JSON。应使用`json.dumps()`生成。
### 15.2 JSON使用单引号
JSON属性名和字符串必须使用双引号。接口工具中输入单引号通常会导致400错误。
### 15.3 最后一项后保留逗号
JSON标准不允许尾随逗号。编辑器中的JavaScript对象可能允许,但JSON解析器通常拒绝。
### 15.4 直接序列化不支持的对象
`Decimal`、日期时间和ORM对象不能默认转换。应先转换为接口明确约定的字符串、数字或字典。
### 15.5 解析成功就直接写数据库
JSON语法正确不等于业务有效。服务器还要校验必填字段、长度、数值范围和权限。
### 15.6 把敏感字段放入响应
对象能序列化不代表所有字段都应返回。密码、密钥和内部状态必须排除。
## 十六、课堂练习
打开`practice.py`,依次完成基本转换、错误处理和HTTP消息观察。练习文件不包含答案。
## 十七、本课小结
JSON是文本格式,不是Python字典。`json.dumps()`负责序列化,`json.loads()`负责反序列化。HTTP通过`Content-Type`声明正文是JSON,语法解析之后仍要进行业务校验。
## 十八、验收标准
- 能区分Python对象、JSON文本和UTF-8字节;
- 能说出JSON支持的六类值;
- 能独立完成序列化和反序列化;
- 能解释`ensure_ascii`和`indent`的作用;
- 能识别单引号、尾随逗号等格式错误;
- 能说明JSON语法校验与业务字段校验的区别;
- 示例可独立运行;
- 完成`practice.py`中的练习。