面向人群:刚学完 Python 基础语法的零基础学员;核心目标:无需任何前置技术常识,就能完全理解 JSON 的本质、Python JSON 模块的所有用法、实战场景与避坑技巧;内容承诺:全程用 “现实类比” 替代专业术语,所有代码均带逐行注释,所有错误均带 “错误代码→原因→解决方案”。
【前置认知篇】:JSON 是什么?为什么要学它?
1.1 用 “现实类比” 理解 JSON 的本质
假设你是一个中国学生,要给美国的笔友寄一份礼物,礼物是 “中国特色的笔记本”。为了让美国的快递员能看懂包装上的信息,你需要:
- 用统一的英文写地址(不能用中文);
- 用统一的格式写收件人、寄件人、邮编(不能随便写);
- 用统一的包装标准打包(不能用中国的特有包装)。
JSON 就是不同软件 / 编程语言之间传输数据的 “统一包装标准”:
- 它是一种文本格式(就像快递包装上的英文说明),任何软件都能看懂;
- 它有严格的语法规则(就像快递的统一格式),任何软件都能解析;
- 它支持多种数据类型(就像快递的多种包装方式),能满足大多数场景。
1.2 为什么 Python 需要 JSON?
Python 中的数据(比如列表、字典)是 **“内存中的临时数据”,就像你手里的 “笔记本”;如果要把它保存到文件 **(就像把笔记本装进快递箱)或者传给其他软件 / 语言(就像把快递寄给美国笔友),就需要用 JSON 这种 “统一包装标准” 来转换。
举个最直观的例子:
- 你用 Python 写了一个学生管理系统,要把学生信息保存到电脑上,总不能让信息关了电脑就消失吧?这时候就需要用 JSON 把 Python 的字典 / 列表转成文本文件保存。
- 你用 Python 写了一个爬虫,要爬取网站上的商品信息,网站返回的就是JSON 格式的数据,你需要用 Python 的 JSON 模块把它转成 Python 能处理的字典 / 列表。
1.3 JSON 的 “官方定义”(零基础可跳过,但建议了解)
JSON 的全称是JavaScript Object Notation(JavaScript 对象表示法),它最初是 JavaScript 的一部分,但现在已经成为跨语言的通用数据格式,几乎所有编程语言都支持 JSON 的解析和生成。
【JSON 语法篇】:严格到 “错一个符号就报错” 的规则
JSON 的语法是世界上最严格的语法之一,任何一个符号错误(比如用了单引号、多了一个逗号)都会导致解析失败。零基础必须一字不差地记住以下 6 条语法规则,每条规则都配有正确示例 + 错误示例 + 原因说明。
2.1 JSON 支持的 6 种基础数据类型
| JSON 类型 | 含义 | 语法规则 | 正确示例 | 错误示例 | 错误原因 |
|---|---|---|---|---|---|
| 字符串 | 文本内容 | 必须用双引号包裹,不能用单引号;支持转义符(比如 \n 表示换行) | "name": "张三" | 'name': '张三' | 用了单引号 |
| 数字 | 整数 / 浮点数 | 支持正负、小数、科学计数法;不能用引号包裹 | "age": 18 | "age": "18" | 用了引号 |
| 布尔值 | 是 / 否 | 只能用true或false(全小写,不能用 True/False) | "is_student": true | "is_student": True | 用了大写 T |
| null | 空值 | 只能用null(全小写,对应 Python 的 None) | "address": null | "address": Null | 用了大写 N |
| 数组 | 有序的列表 | 用 **[]** 包裹,元素之间用逗号分隔;元素可以是任何 JSON 类型 | "courses": ["数学", "语文"] | "courses": [数学, 语文] | 元素没加双引号 |
| 对象 | 无序的键值对集合 | 用 **{}** 包裹,键必须用双引号,值可以是任何 JSON 类型;键值对之间用逗号分隔;不能有末尾逗号 | "student": {"name": "张三", "age": 18} | "student": {"name": "张三", "age": 18,} | 末尾多了逗号 |
2.2 JSON 的 “嵌套规则”(核心难点)
JSON 支持无限嵌套:
- 数组里可以嵌套数组、对象;
- 对象里可以嵌套对象、数组。
正确嵌套示例(学生信息 + 课程信息 + 成绩信息):
{
"id": "2024052001",
"name": "张三",
"age": 18,
"is_student": true,
"address": null,
"courses": [
{"name": "数学", "score": 95},
{"name": "语文", "score": 90}
]
}
错误嵌套示例:
{
"id": 2024052001,
"name": '张三', // 错误:单引号
"courses": [ // 错误:数组元素没有双引号包裹?不,这里是对象,没问题,但下面的score用了单引号
{"name": "数学", 'score': 95}, // 错误:单引号
{"name": "语文", "score": 90}, // 错误:末尾多了逗号
]
}
2.3 在线 JSON 校验工具(零基础必备)
如果你的 JSON 格式总是报错,永远不要自己找错,直接用在线 JSON 校验工具:
- 推荐工具:https://jsonlint.com/
- 使用方法:把你的 JSON 字符串粘贴进去,工具会自动指出错误位置和原因。
【Python JSON 模块基础篇】:4 个核心函数的 “逐行详解”
Python 自带了json 模块(无需安装),它的核心功能是 “Python 数据↔JSON 格式” 的转换,对应 4 个核心函数:
⚠️ 零基础必须先记住:dumps/loads 是 “字符串转换”,dump/load 是 “文件转换”—— 这是最容易混淆的点!
3.1 函数 1:json.dumps () → 把 Python 数据 “打包” 成 JSON 字符串
3.1.1 函数名含义
dumps是dump string的缩写,意思是 “把 Python 数据 dump 成 JSON 字符串”。
3.1.2 基础用法(逐行详解)
# 1. 导入Python自带的json模块(必须先导入才能用)
import json
# 2. 准备一个Python字典(JSON的对象对应Python的字典)
python_dict = {
"name": "张三", # 键用双引号(Python允许单引号,但JSON必须双引号,dumps会自动转换)
"age": 18, # 数字类型(JSON的数字对应Python的int/float)
"is_student": True, # 布尔值(JSON的true对应Python的True)
"address": None # 空值(JSON的null对应Python的None)
}
# 3. 把Python字典转成JSON字符串
json_str = json.dumps(python_dict)
# 4. 打印结果
print("JSON字符串:", json_str)
print("JSON字符串的类型:", type(json_str)) # <class 'str'>
运行结果:
JSON字符串: {"name": "\u5f20\u4e09", "age": 18, "is_student": true, "address": null}
JSON字符串的类型: <class 'str'>
3.1.3 常见问题:中文变成了 “\u5f20\u4e09”?
这是因为json.dumps()的默认参数ensure_ascii=True,它会把中文转换成Unicode 编码(\u 开头的十六进制)。要让中文正常显示,必须加ensure_ascii=False:
# 正确写法:加ensure_ascii=False
json_str = json.dumps(python_dict, ensure_ascii=False)
print("JSON字符串(中文正常):", json_str)
运行结果:
JSON字符串(中文正常): {"name": "张三", "age": 18, "is_student": true, "address": null}
3.1.4 美化输出:让 JSON 更易读(indent 参数)
默认的 JSON 字符串是 “紧凑格式”,没有换行和缩进,人很难看。用 **indent=N** 参数可以让 JSON 字符串 “美化输出”,N 是缩进的空格数:
# 美化输出:缩进2个空格
json_str = json.dumps(python_dict, ensure_ascii=False, indent=2)
print("美化后的JSON字符串:", json_str)
运行结果:
美化后的JSON字符串: {
"name": "张三",
"age": 18,
"is_student": true,
"address": null
}
3.1.5 其他常用参数
sort_keys=True:把 JSON 的键按字母顺序排序(默认 False):json_str = json.dumps(python_dict, ensure_ascii=False, sort_keys=True) print(json_str) # {"address": null, "age": 18, "is_student": true, "name": "张三"}separators=(",", ":"):去掉 JSON 中的空格,让字符串更紧凑(默认是 (",", ":"),即逗号和冒号后有空格):json_str = json.dumps(python_dict, ensure_ascii=False, separators=(",", ":")) print(json_str) # {"name":"张三","age":18,"is_student":true,"address":null}
3.1.6 支持的 Python 数据类型
| Python 类型 | JSON 类型 |
|---|---|
| dict | object |
| list/tuple | array |
| str | string |
| int/float | number |
| True | true |
| False | false |
| None | null |
注意:Python 的tuple转成 JSON 后会变成array(因为 JSON 没有 tuple 类型):
python_tuple = ("数学", "语文", "英语")
json_str = json.dumps(python_tuple, ensure_ascii=False)
print(json_str) # ["数学", "语文", "英语"]
3.2 函数 2:json.loads () → 把 JSON 字符串 “拆包” 成 Python 数据
3.2.1 函数名含义
loads是load string的缩写,意思是 “把 JSON 字符串 load 成 Python 数据”。
3.2.2 基础用法(逐行详解)
import json
# 1. 准备一个JSON字符串(必须用双引号!)
json_str = '{"name": "张三", "age": 18, "is_student": true, "address": null, "courses": ["数学", "语文"]}'
# 2. 把JSON字符串转成Python数据
python_data = json.loads(json_str)
# 3. 打印结果
print("Python数据:", python_data)
print("Python数据的类型:", type(python_data)) # <class 'dict'>
print("Python数据的name字段:", python_data["name"]) # 张三
print("Python数据的courses字段:", python_data["courses"]) # ['数学', '语文']
print("courses字段的类型:", type(python_data["courses"])) # <class 'list'>
3.2.3 常见错误 1:JSON 字符串用了单引号
错误代码:
json_str = "{'name': '张三'}" # 用了单引号
python_data = json.loads(json_str) # 报错:JSONDecodeError
错误原因:JSON 的字符串必须用双引号,Python 的 json 模块严格遵循 JSON 语法。解决方案:把所有单引号改成双引号,或者用json.dumps()生成的 JSON 字符串(自动用双引号)。
3.2.4 常见错误 2:JSON 字符串有末尾逗号
错误代码:
json_str = '{"name": "张三", "age": 18,}' # 末尾多了逗号
python_data = json.loads(json_str) # 报错:JSONDecodeError
解决方案:去掉末尾的逗号。
3.2.5 常见错误 3:JSON 字符串有注释
错误代码:
json_str = '{"name": "张三", "age": 18}' # 注释
python_data = json.loads(json_str) # 报错:JSONDecodeError
错误原因:JSON 语法不支持注释!解决方案:去掉注释,或者用JSON5格式(支持注释,但需要安装第三方库json5)。
3.3 函数 3:json.dump () → 把 Python 数据 “打包” 成 JSON 写入文件
3.3.1 函数名含义
dump是dump file的缩写,意思是 “把 Python 数据 dump 成 JSON 写入文件”。
3.3.2 基础用法(逐行详解)
import json
# 1. 准备一个Python字典
python_dict = {"name": "张三", "age": 18, "courses": ["数学", "语文"]}
# 2. 打开文件,准备写入JSON数据
# 参数说明:
# - "data.json":文件名(保存在当前Python脚本的目录下)
# - "w":写入模式(覆盖原有内容;如果要追加,用"a",但JSON一般不用追加)
# - encoding="utf-8":防止中文乱码(必须加!)
with open("data.json", "w", encoding="utf-8") as f:
# 3. 把Python字典转成JSON写入文件
# ensure_ascii=False:中文正常显示
# indent=2:美化写入
json.dump(python_dict, f, ensure_ascii=False, indent=2)
print("JSON文件写入成功!")
运行结果:
- 你的 Python 脚本目录下会生成一个
data.json文件,打开后内容是:{ "name": "张三", "age": 18, "courses": [ "数学", "语文" ] }
3.3.3 为什么用with语句?
with语句是 Python 的 “上下文管理器”,它会自动关闭文件,避免出现 “文件没关闭导致数据丢失” 的问题。如果不用with语句,你需要手动写f.close():
f = open("data.json", "w", encoding="utf-8")
json.dump(python_dict, f, ensure_ascii=False, indent=2)
f.close() # 必须手动关闭!
3.4 函数 4:json.load () → 从 JSON 文件 “拆包” 成 Python 数据
3.4.1 函数名含义
load是load file的缩写,意思是 “从 JSON 文件 load 成 Python 数据”。
3.4.2 基础用法(逐行详解)
import json
# 1. 打开JSON文件,准备读取
# 参数说明:
# - "data.json":要读取的文件名
# - "r":读取模式
# - encoding="utf-8":防止中文乱码(必须加!)
with open("data.json", "r", encoding="utf-8") as f:
# 2. 把JSON文件内容转成Python数据
python_data = json.load(f)
# 3. 打印结果
print("从JSON文件读取的Python数据:", python_data)
print("Python数据的类型:", type(python_data)) # <class 'dict'>
print("学生姓名:", python_data["name"]) # 张三
3.4.3 常见错误:文件不存在或路径错误
错误代码:
with open("wrong_path/data.json", "r", encoding="utf-8") as f:
python_data = json.load(f) # 报错:FileNotFoundError
解决方案:
- 确保文件名拼写正确;
- 确保文件路径正确:
- 如果文件和 Python 脚本在同一个目录,直接写文件名即可(如
"data.json"); - 如果文件在脚本的子目录,写
"子目录名/文件名"(如"data/data.json"); - 如果是绝对路径(Windows),写
"D:/data/data.json"(注意用/或\\)。
- 如果文件和 Python 脚本在同一个目录,直接写文件名即可(如
3.4.4 常见错误:文件内容不是 JSON 格式
错误代码:
# data.json的内容是:name=张三, age=18(不是JSON格式)
with open("data.json", "r", encoding="utf-8") as f:
python_data = json.load(f) # 报错:JSONDecodeError
解决方案:确保文件内容是严格符合 JSON 语法的字符串,推荐用json.dump()生成 JSON 文件。
【JSON 模块进阶篇】:解决 “不支持的类型” 与 “自定义转换”
前面我们说过,JSON 只支持 6 种基础类型,而 Python 有很多不支持的类型(比如 datetime、set、自定义类等)。这部分我们会讲怎么处理这些 “特殊类型”,以及如何自定义 JSON 的转换规则。
4.1 问题 1:Python 的 datetime 类型不能直接转换
错误代码:
import json
from datetime import datetime
# 准备包含datetime类型的Python数据
python_data = {
"name": "张三",
"register_time": datetime.now() # datetime类型,JSON不支持
}
json_str = json.dumps(python_data, ensure_ascii=False) # 报错:Object of type datetime is not JSON serializable
错误原因:JSON 没有 “时间” 类型,所以无法直接转换 Python 的 datetime。
4.1.1 解决方案 1:手动转成字符串
把 datetime 转成ISO 格式的字符串(JSON 支持的字符串类型):
# 转成ISO格式:%Y-%m-%d %H:%M:%S
python_data["register_time"] = python_data["register_time"].strftime("%Y-%m-%d %H:%M:%S")
json_str = json.dumps(python_data, ensure_ascii=False)
print(json_str) # {"name": "张三", "register_time": "2024-05-20 15:30:00"}
4.1.2 解决方案 2:自定义 JSON 编码器(企业级推荐)
如果你的项目中有很多 datetime 类型需要转换,手动转换太麻烦,可以自定义 JSON 编码器—— 继承json.JSONEncoder类,重写default方法:
import json
from datetime import datetime
# 自定义JSON编码器
class MyEncoder(json.JSONEncoder):
def default(self, obj):
# 如果obj是datetime类型,转成ISO格式的字符串
if isinstance(obj, datetime):
return obj.strftime("%Y-%m-%d %H:%M:%S")
# 如果obj是其他不支持的类型,调用父类的default方法(会报错,符合预期)
return super().default(obj)
# 准备数据
python_data = {"name": "张三", "register_time": datetime.now()}
# 用cls参数指定自定义编码器
json_str = json.dumps(python_data, ensure_ascii=False, cls=MyEncoder)
print(json_str) # {"name": "张三", "register_time": "2024-05-20 15:30:00"}
4.2 问题 2:Python 的 set 类型不能直接转换
错误代码:
import json
python_data = {"name": "张三", "courses": {"数学", "语文"}} # set类型
json_str = json.dumps(python_data, ensure_ascii=False) # 报错:Object of type set is not JSON serializable
解决方案:转成 list 类型(JSON 支持的 array 类型):
python_data["courses"] = list(python_data["courses"])
json_str = json.dumps(python_data, ensure_ascii=False)
print(json_str) # {"name": "张三", "courses": ["数学", "语文"]}(顺序可能随机,因为set是无序的)
4.3 问题 3:自定义类不能直接转换
错误代码:
import json
# 自定义一个学生类
class Student:
def __init__(self, name, age):
self.name = name
self.age = age
# 创建学生对象
student = Student("张三", 18)
json_str = json.dumps(student, ensure_ascii=False) # 报错:Object of type Student is not JSON serializable
解决方案:
- 把类的属性转成字典(用
vars()函数或__dict__属性); - 或者用自定义编码器。
4.3.1 方法 1:用 vars () 函数转成字典
# vars()函数会返回对象的属性字典
python_dict = vars(student) # {"name": "张三", "age": 18}
json_str = json.dumps(python_dict, ensure_ascii=False)
print(json_str) # {"name": "张三", "age": 18}
4.3.2 方法 2:用自定义编码器
class StudentEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, Student):
return {"name": obj.name, "age": obj.age}
return super().default(obj)
json_str = json.dumps(student, ensure_ascii=False, cls=StudentEncoder)
print(json_str) # {"name": "张三", "age": 18}
4.4 问题 4:把 JSON 字符串转成 Python 的 datetime 类型(自定义解码器)
前面我们讲了把 datetime 转成 JSON 字符串,现在我们要反过来 —— 把 JSON 的时间字符串转成 Python 的 datetime 类型:
import json
from datetime import datetime
# 准备JSON字符串
json_str = '{"name": "张三", "register_time": "2024-05-20 15:30:00"}'
# 自定义解码器函数:把JSON的字典转成Python的字典,如果有register_time字段,转成datetime
def my_decoder(dct):
# 如果dct中有"register_time"键
if "register_time" in dct:
# 用strptime()转成datetime类型,格式要和JSON中的字符串一致
dct["register_time"] = datetime.strptime(dct["register_time"], "%Y-%m-%d %H:%M:%S")
# 返回转换后的字典
return dct
# 用object_hook参数指定自定义解码器
python_data = json.loads(json_str, object_hook=my_decoder)
print(python_data) # {'name': '张三', 'register_time': datetime.datetime(2024, 5, 20, 15, 30)}
print(type(python_data["register_time"])) # <class 'datetime.datetime'>
【项目实战篇】:用 JSON 做 “学生管理系统的数据存储”
前面我们学了 JSON 的所有基础和进阶用法,现在我们用JSON 作为数据存储,做一个完整的学生管理系统(零基础可直接运行,带所有注释)。
5.1 项目需求(和之前的学生管理系统一致)
- 显示菜单:1. 添加学生 2. 删除学生 3. 查询学生 4. 修改成绩 5. 退出系统
- 数据持久化:关了系统再打开,学生信息还在
- 支持学号唯一、模糊查询、成绩修改
5.2 项目结构(只有一个文件,适合零基础)
student_management.py # 主程序文件
student_data.json # JSON数据文件(自动生成)
5.3 完整代码(逐行注释)
# student_management.py
import json
# -------------------------- 1. 数据文件路径 --------------------------
DATA_FILE = "student_data.json"
# -------------------------- 2. 初始化:从JSON文件读取数据 --------------------------
def load_students():
"""
从JSON文件读取学生数据,返回学生列表
如果文件不存在或格式错误,返回空列表
"""
try:
with open(DATA_FILE, "r", encoding="utf-8") as f:
students = json.load(f)
print(f"成功读取{len(students)}条学生数据!")
return students
except FileNotFoundError:
# 第一次运行系统,文件不存在,返回空列表
print("数据文件不存在,将创建新文件!")
return []
except json.JSONDecodeError:
# 文件内容格式错误,返回空列表
print("数据文件格式错误,将重置为新文件!")
return []
# -------------------------- 3. 保存数据到JSON文件 --------------------------
def save_students(students):
"""
把学生列表保存到JSON文件
"""
try:
with open(DATA_FILE, "w", encoding="utf-8") as f:
json.dump(students, f, ensure_ascii=False, indent=2)
print("数据保存成功!")
except Exception as e:
print(f"数据保存失败:{e}")
# -------------------------- 4. 显示菜单 --------------------------
def show_menu():
print("=" * 40)
print(" 学生管理系统 V1.0")
print("1. 添加学生信息")
print("2. 删除学生信息")
print("3. 查询学生信息")
print("4. 修改学生成绩")
print("5. 退出系统")
print("=" * 40)
# -------------------------- 5. 添加学生 --------------------------
def add_student(students):
"""
添加学生信息,确保学号唯一
"""
# 获取学生信息
student_id = input("请输入学号:")
name = input("请输入姓名:")
age = int(input("请输入年龄:")) # 转成整数
math_score = float(input("请输入数学成绩:")) # 转成浮点数
chinese_score = float(input("请输入语文成绩:")) # 转成浮点数
# 检查学号是否唯一
for student in students:
if student["id"] == student_id:
print("添加失败!学号已存在!")
return
# 构造学生字典
new_student = {
"id": student_id,
"name": name,
"age": age,
"math_score": math_score,
"chinese_score": chinese_score
}
# 添加到学生列表
students.append(new_student)
print("添加学生成功!")
# -------------------------- 6. 删除学生 --------------------------
def delete_student(students):
"""
根据学号删除学生
"""
student_id = input("请输入要删除的学号:")
# 遍历学生列表,用enumerate获取索引
for index, student in enumerate(students):
if student["id"] == student_id:
del students[index] # 删除该学生
print("删除学生成功!")
return
print("删除失败!未找到该学号的学生!")
# -------------------------- 7. 查询学生 --------------------------
def query_student(students):
"""
模糊查询(学号或姓名包含关键词)
"""
keyword = input("请输入查询关键词(学号或姓名):")
# 存放查询结果
results = []
for student in students:
# 把学号和姓名转成小写,支持大小写不敏感查询
if keyword.lower() in student["id"].lower() or keyword.lower() in student["name"].lower():
results.append(student)
# 打印查询结果
if results:
print("查询结果如下:")
print("-" * 50)
for student in results:
print(f"学号:{student['id']}")
print(f"姓名:{student['name']}")
print(f"年龄:{student['age']}")
print(f"数学成绩:{student['math_score']}")
print(f"语文成绩:{student['chinese_score']}")
print("-" * 50)
else:
print("未找到符合条件的学生!")
# -------------------------- 8. 修改学生成绩 --------------------------
def modify_score(students):
"""
修改学生的数学或语文成绩
"""
student_id = input("请输入要修改的学号:")
# 选择要修改的科目
while True:
print("1. 修改数学成绩")
print("2. 修改语文成绩")
try:
choice = int(input("请选择要修改的科目:"))
if choice == 1:
subject = "math_score"
break
elif choice == 2:
subject = "chinese_score"
break
else:
print("输入错误!请输入1或2!")
except ValueError:
print("输入错误!请输入数字!")
# 获取新成绩
new_score = float(input(f"请输入新的{subject}:"))
# 修改成绩
for student in students:
if student["id"] == student_id:
student[subject] = new_score
print("修改成绩成功!")
return
print("修改失败!未找到该学号的学生!")
# -------------------------- 9. 主程序入口 --------------------------
def main():
# 1. 读取已有的学生数据
students = load_students()
# 2. 主循环
while True:
# 显示菜单
show_menu()
# 获取用户选择
try:
choice = int(input("请输入您的选择(1-5):"))
if choice == 1:
add_student(students)
save_students(students) # 添加后立即保存
elif choice == 2:
delete_student(students)
save_students(students) # 删除后立即保存
elif choice == 3:
query_student(students)
elif choice == 4:
modify_score(students)
save_students(students) # 修改后立即保存
elif choice == 5:
print("正在退出系统...")
save_students(students) # 退出前保存
print("系统已退出!")
break
else:
print("输入错误!请输入1-5之间的数字!")
except ValueError:
print("输入错误!请输入数字!")
# -------------------------- 运行主程序 --------------------------
if __name__ == "__main__":
main()
5.4 运行测试(零基础必做)
- 把上述代码保存为
student_management.py; - 打开 cmd,进入文件所在目录,输入
python student_management.py; - 按菜单提示操作:添加学生→查询学生→修改成绩→删除学生→退出系统;
- 退出后再次运行系统,你会发现之前添加的学生信息还在(因为保存到了
student_data.json文件)。
【避坑总结篇】:零基础常犯的 15 个 JSON 错误
6.1 错误 1:dump/dumps 混淆
错误代码:
json.dump(python_dict) # 报错:dump() missing 1 required positional argument: 'fp'
原因:dump是写入文件,需要两个参数(Python 数据 + 文件对象);dumps是转成字符串,只需要一个参数(Python 数据)。解决方案:区分 “字符串转换” 和 “文件转换”。
6.2 错误 2:load/loads 混淆
错误代码:
json.load(json_str) # 报错:load() missing 1 required positional argument: 'fp'
原因:load是从文件读取,需要文件对象;loads是从字符串读取,需要 JSON 字符串。
6.3 错误 3:JSON 字符串用单引号
错误代码:
json_str = '{'name': '张三'}' # 语法错误,Python会报错
解决方案:用双引号包裹 JSON 字符串,或者用转义符:
json_str = '{"name": "张三"}' # 正确
json_str = "{\"name\": \"张三\"}" # 用转义符
6.4 错误 4:ensure_ascii=True 导致中文乱码
错误代码:
json_str = json.dumps({"name": "张三"}) # 结果:{"name": "\u5f20\u4e09"}
解决方案:加ensure_ascii=False。
6.5 错误 5:忘记加 encoding='utf-8'
错误代码:
with open("data.json", "w") as f:
json.dump({"name": "张三"}, f, ensure_ascii=False) # 报错:UnicodeEncodeError
解决方案:打开文件时加encoding="utf-8"。
6.6 错误 6:JSON 对象 / 数组有末尾逗号
错误代码:
json_str = '{"name": "张三", "age": 18,}'
解决方案:去掉末尾的逗号。
6.7 错误 7:JSON 支持注释
错误代码:
json_str = '{"name": "张三"} // 这是注释'
解决方案:去掉注释,或用 JSON5 格式(安装pip install json5,然后用json5.loads())。
6.8 错误 8:Python 的 set/tuple 直接转换
错误代码:
json.dumps({"courses": {"数学", "语文"}}) # set类型报错
解决方案:转成 list 类型。
6.9 错误 9:datetime 类型直接转换
解决方案:转成字符串或用自定义编码器。
6.10 错误 10:文件路径错误
解决方案:用相对路径或正确的绝对路径。
6.11 错误 11:JSON 字符串的键是数字
错误代码:
json_str = '{123: "张三"}' # JSON的键必须是字符串
解决方案:键用双引号包裹:{"123": "张三"}。
6.12 错误 12:Python 的 True/False 写成大写
错误代码:
json_str = '{"is_student": True}' # JSON的布尔值必须小写
解决方案:写成true/false。
6.13 错误 13:Python 的 None 写成 Null
错误代码:
json_str = '{"address": Null}' # JSON的空值必须小写
解决方案:写成null。
6.14 错误 14:美化输出时忘记加 ensure_ascii=False
错误代码:
json.dumps({"name": "张三", indent=2}) # 中文还是乱码
解决方案:同时加ensure_ascii=False和indent=2。
6.15 错误 15:用 print () 生成 JSON 字符串
错误代码:
# 手动拼接JSON字符串,容易出错
json_str = '{"name": "' + name + '", "age": ' + str(age) + '}'
解决方案:用json.dumps()生成 JSON 字符串,自动处理引号和类型转换。
【结尾篇】:零基础学习 JSON 模块的 “正确姿势”
7.1 不要死记硬背语法
用现实类比理解 JSON 的本质:“统一的快递包装标准”,语法规则就是 “包装要求”,错一个就寄不出去。
7.2 先练基础,再练进阶
- 先练
dumps/loads的字符串转换,确保能正确转换字典和列表; - 再练
dump/load的文件转换,确保能正确保存和读取数据; - 最后练进阶的自定义编码器 / 解码器。
7.3 多用在线工具校验 JSON 格式
如果 JSON 格式报错,第一时间用jsonlint.com校验,不要自己找错。
7.4 多做实战
用 JSON 做配置文件读取、API 数据交互、小项目数据存储,比如:
- 把你的爬虫结果保存到 JSON 文件;
- 把你的小工具的配置(比如用户名、密码)保存到 JSON 文件;
- 用 JSON 模拟 API 的返回数据。

被折叠的 条评论
为什么被折叠?



