零基础全面掌握 Python JSON 模块:从 “什么是 JSON” 到 “企业级实战” 的 16000 字指南

编程达人挑战赛·第6期 10w+人浏览 208人参与

面向人群:刚学完 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"用了引号
布尔值是 / 否只能用truefalse(全小写,不能用 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 函数名含义

dumpsdump 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 类型
dictobject
list/tuplearray
strstring
int/floatnumber
Truetrue
Falsefalse
Nonenull

注意: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 函数名含义

loadsload 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 函数名含义

dumpdump 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 函数名含义

loadload 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

解决方案

  1. 确保文件名拼写正确;
  2. 确保文件路径正确:
    • 如果文件和 Python 脚本在同一个目录,直接写文件名即可(如"data.json");
    • 如果文件在脚本的子目录,写"子目录名/文件名"(如"data/data.json");
    • 如果是绝对路径(Windows),写"D:/data/data.json"(注意用/\\)。

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

解决方案

  1. 把类的属性转成字典(用vars()函数或__dict__属性);
  2. 或者用自定义编码器。

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. 显示菜单:1. 添加学生 2. 删除学生 3. 查询学生 4. 修改成绩 5. 退出系统
  2. 数据持久化:关了系统再打开,学生信息还在
  3. 支持学号唯一、模糊查询、成绩修改

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 运行测试(零基础必做)

  1. 把上述代码保存为student_management.py
  2. 打开 cmd,进入文件所在目录,输入python student_management.py
  3. 按菜单提示操作:添加学生→查询学生→修改成绩→删除学生→退出系统;
  4. 退出后再次运行系统,你会发现之前添加的学生信息还在(因为保存到了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=Falseindent=2

6.15 错误 15:用 print () 生成 JSON 字符串

错误代码

# 手动拼接JSON字符串,容易出错
json_str = '{"name": "' + name + '", "age": ' + str(age) + '}'

解决方案:用json.dumps()生成 JSON 字符串,自动处理引号和类型转换。


【结尾篇】:零基础学习 JSON 模块的 “正确姿势”

7.1 不要死记硬背语法

现实类比理解 JSON 的本质:“统一的快递包装标准”,语法规则就是 “包装要求”,错一个就寄不出去。

7.2 先练基础,再练进阶

  1. 先练dumps/loads的字符串转换,确保能正确转换字典和列表;
  2. 再练dump/load的文件转换,确保能正确保存和读取数据;
  3. 最后练进阶的自定义编码器 / 解码器。

7.3 多用在线工具校验 JSON 格式

如果 JSON 格式报错,第一时间用jsonlint.com校验,不要自己找错。

7.4 多做实战

用 JSON 做配置文件读取API 数据交互小项目数据存储,比如:

  • 把你的爬虫结果保存到 JSON 文件;
  • 把你的小工具的配置(比如用户名、密码)保存到 JSON 文件;
  • 用 JSON 模拟 API 的返回数据。

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值