Files
PythonLearn/05_web基础/5_4_JSON数据交换

第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程序内,不能原样作为跨语言约定。

双方需要一种共同格式:

Python字典 → JSON文本 → HTTP传输 → JSON文本 → JavaScript对象

JavaScript对象表示法(JavaScript Object Notation,JSON)是一种轻量的文本数据格式。它由字符组成,与具体编程语言无关,因此非常适合Web接口交换结构化数据。

四、不要混淆三个层次

下面三项表示相近内容,但类型不同:

# 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和自定义类等专用类型。发送这些值之前,需要先决定明确的表示形式。

例如日期时间通常转换成字符串:

{"created_at": "2026-08-20T10:30:00+08:00"}

这只是常见约定,客户端和服务器仍需在接口文档中统一格式与时区。

六、阅读一段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文本:

json_text = json.dumps(book, ensure_ascii=False, indent=2)

参数含义:

  • book:需要转换的Python对象;
  • ensure_ascii=False:中文直接保留,不显示成Unicode转义;
  • indent=2:每层缩进两个空格,便于人阅读。

格式化缩进会增加数据大小,生产接口是否缩进由项目性能和可读性要求决定。

八、反序列化

反序列化(Deserialization)是把JSON文本还原为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时,应声明请求体格式:

POST /books HTTP/1.1
Content-Type: application/json; charset=utf-8

{"title": "Python入门"}

服务器返回JSON时,也应声明响应体格式:

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字典;
  • 从解析结果中读取书名。

十一、运行方法

cd D:\Code\Python\05_web基础\5_4_JSON数据交换
python json_rest_example.py

十二、预期结果

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中的练习。