当前位置: 首页 > news >正文

Python JSON 全方位解析:序列化、反序列化与实战技巧

在 Python 开发中,JSON(JavaScript Object Notation)是前后端数据交互、跨平台数据传输的核心格式。它轻量、易读且兼容性强,几乎所有编程语言都支持 JSON 解析。本文将结合实战代码,从 JSON 基础概念出发,详细讲解 Python 中 JSON 的序列化(Python 数据转 JSON)、反序列化(JSON 转 Python 数据)、高级配置(美化、特殊类型处理)及文件读写操作,帮助你彻底掌握 JSON 处理技巧。


一、JSON 核心概念与 Python 数据映射

在开始代码实战前,需先明确 JSON 的格式规则及与 Python 数据类型的对应关系 —— 这是正确处理 JSON 的基础。

1.1 JSON 格式规则

JSON 本质是一种字符串格式,有严格的语法要求,常见错误(如单引号、元组)会导致解析失败,核心规则如下:

  • 字符串必须用 双引号"name" 正确,'name' 错误);
  • 支持的数据类型:对象(对应 Python 字典)、数组(对应 Python 列表)、字符串、数字、布尔值(true/false)、null(对应 Python None);
  • 不支持 Python 特有的类型:集合(set)、元组(tuple)、datetime 等(需特殊处理)。

示例:

// 正确 JSON 格式(对象)
{"name":"mary","age":20,"is_student":true,"hobby":null}// 正确 JSON 格式(数组)
[10, 20, "hello", {"city":"New York"}]

1.2 JSON 与 Python 数据类型映射表

JSON 与 Python 数据类型并非完全一一对应,序列化 / 反序列化时会自动转换,对应关系如下:

Python 数据类型JSON 数据类型反序列化后 Python 类型
dict对象({}dict
list/tuple数组([]list(元组会转列表)
str字符串str
int/float数字int/float
TruetrueTrue
FalsefalseFalse
NonenullNone
set/datetime不支持需自定义处理(见 3.2 节

二、基础操作:JSON 序列化与反序列化

Python 内置 json 模块,提供 dumps()/loads() 两个核心函数,分别实现 “Python 数据转 JSON 字符串” 和 “JSON 字符串转 Python 数据”。

2.1 序列化:json.dumps()(Python → JSON 字符串)

json.dumps(obj) 接收 Python 数据(如字典、列表),返回对应的 JSON 字符串。下面通过多类型示例演示其用法:

import json# 1. 数字类型(int)
js_num = json.dumps(10)
print("数字序列化:", js_num)          # 输出:"10"(JSON 字符串)
print("类型:", type(js_num))          # 输出:<class 'str'># 2. None(对应 JSON null)
js_none = json.dumps(None)
print("\nNone 序列化:", js_none)      # 输出:"null"
print("反序列化后类型:", type(json.loads(js_none)))  # 输出:<class 'NoneType'># 3. 布尔值(True/False)
js_bool = json.dumps(True)
print("\n布尔值序列化:", js_bool)     # 输出:"true"(JSON 小写)
print("反序列化后值:", json.loads(js_bool))  # 输出:True# 4. 列表(含混合类型)
js_list = json.dumps([10, 20, 'hello'])
print("\n列表序列化:", js_list)       # 输出:"[10, 20, \"hello\"]"(双引号转义)
print("反序列化后:", json.loads(js_list))  # 输出:[10, 20, 'hello']# 5. 字典(key 需为字符串/数字,不支持元组)
js_dict = json.dumps({'name': 'mary', 'age': 20, None: 'hello'})
print("\n字典序列化:", js_dict)       # 输出:"{"name":"mary","age":20,"null":"hello"}"(None 转 null 作为 key)
print("反序列化后:", json.loads(js_dict))  # 输出:{'name': 'mary', 'age': 20, 'null': 'hello'}# 6. 嵌套结构(列表+字典)
js_nested = json.dumps([{'name': 'mary', 'age': 20}, {'name': 'tom', 'age': 30}])
print("\n嵌套结构序列化:", js_nested)  # 输出:"[{"name":"mary","age":20},{"name":"tom","age":30}]"
print("反序列化后:", json.loads(js_nested))  # 输出:[{'name': 'mary', 'age': 20}, {'name': 'tom', 'age': 30}]# ❌ 不支持的类型:集合(会抛 TypeError)
# js_set = json.dumps({12, 22, 'world'})  # 报错:TypeError: Object of type set is not JSON serializable

2.2 反序列化:json.loads()(JSON 字符串 → Python 数据)

json.loads(json_str) 接收 JSON 格式的字符串,返回对应的 Python 数据。需注意:输入必须是严格的 JSON 字符串(双引号、无非法类型)。

import json# 1. JSON 字符串(对象)转 Python 字典
json_str1 = '{"name":"张三","age":20,"is_student":true,"hobby":null}'
py_dict = json.loads(json_str1)
print("JSON 对象转字典:", py_dict)
print("类型:", type(py_dict))  # 输出:<class 'dict'># 2. JSON 字符串(数组)转 Python 列表
json_str2 = '[10, 20, "hello", {"city":"北京"}]'
py_list = json.loads(json_str2)
print("\nJSON 数组转列表:", py_list)
print("类型:", type(py_list))  # 输出:<class 'list'># 3. 特殊值反序列化(null → None,true → True)
json_str3 = '{"score":null, "passed":false}'
py_data = json.loads(json_str3)
print("\n特殊值反序列化:", py_data)  # 输出:{'score': None, 'passed': False}

三、高级配置:美化、特殊类型处理

json.dumps() 提供多个可选参数,支持 JSON 美化、中文显示、特殊类型(如 set/datetime)序列化,满足复杂场景需求。

3.1 常用配置参数(美化、中文、排序)

通过 ensure_asciiindentseparatorssort_keys 四个参数,可自定义 JSON 输出格式:

参数名作用说明
ensure_ascii布尔值,默认 True(中文转义为 \uXXXX),设为 False 可显示中文
indent整数,JSON 缩进空格数(美化输出),默认 None(紧凑格式)
separators元组 (item_sep, key_sep),指定分隔符(默认 (', ', ': ')
sort_keys布尔值,默认 False,设为 True 按字典 key 升序排列

示例:

import json# 原始 Python 数据(含中文)
student = {'name': '张三', 'age': 20, 'sex': '男', 'score': 95}# 应用高级配置
js_pretty = json.dumps(student,ensure_ascii=False,  # 显示中文(不转义)indent=4,            # 缩进 4 个空格(美化)separators=(',', ':'),  # 列表元素用 ',' 分隔,字典 key-value 用 ':' 分隔(无空格)sort_keys=True       # 按 key 升序排列(age < name < score < sex)
)print("美化后的 JSON:")
print(js_pretty)

输出结果(格式清晰,中文正常显示):

{"age":20,"name":"张三","score":95,"sex":"男"
}

3.2 特殊类型处理:default 参数

JSON 不支持 Python 的 setdatetime 等类型,直接序列化会抛 TypeError。此时需通过 default 参数指定自定义处理函数,将特殊类型转换为 JSON 支持的类型(如 set 转 listdatetime 转字符串)。

案例:处理 set 和 datetime 类型
import json
from datetime import datetime# 含特殊类型的 Python 数据
data = {'name': 'mary','hobbys': {'打球', '编程'},  # set 类型(JSON 不支持)'borndate': datetime(2003, 2, 18)  # datetime 类型(JSON 不支持)
}
list_data = [10, 'hello', {'唱歌', '跑步'}]  # 列表含 set# 自定义处理函数:接收无法序列化的对象(obj),返回 JSON 支持的类型
def handle_special_types(obj):# 处理 set 类型:转为 listif isinstance(obj, set):return list(obj)# 处理 datetime 类型:转为字符串(如 "2003-02-18")if isinstance(obj, datetime):return obj.strftime('%Y-%m-%d')# 其他未处理类型:抛异常(可选)raise TypeError(f"不支持的类型:{type(obj)}")# 1. 序列化含特殊类型的字典
js_data = json.dumps(data,ensure_ascii=False,default=handle_special_types  # 指定自定义处理函数
)
print("处理特殊类型的 JSON(字典):")
print(js_data)
print("反序列化后:", json.loads(js_data))  # set 已转为 list,datetime 已转为字符串# 2. 序列化含特殊类型的列表
js_list = json.dumps(list_data,ensure_ascii=False,default=handle_special_types
)
print("\n处理特殊类型的 JSON(列表):")
print(js_list)
print("反序列化后:", json.loads(js_list))

输出结果

处理特殊类型的 JSON(字典):
{"name":"mary","hobbys":["打球","编程"],"borndate":"2003-02-18"}
反序列化后: {'name': 'mary', 'hobbys': ['打球', '编程'], 'borndate': '2003-02-18'}处理特殊类型的 JSON(列表):
[10,"hello",["唱歌","跑步"]]
反序列化后: [10, 'hello', ['唱歌', '跑步']]

四、文件操作:JSON 与文件的交互

实际开发中,JSON 数据常需写入文件(如配置文件)或从文件读取。json 模块提供 dump() 和 load() 函数,直接实现 “Python 数据 ↔ 文件” 的交互,无需手动处理字符串读写。

4.1 序列化到文件:json.dump()

json.dump(obj, file_obj) 将 Python 数据直接写入文件(需以文本模式 w 打开文件),等价于 file.write(json.dumps(obj)),但更简洁。

import json# 待写入文件的 Python 数据
user_list = [{'name': '张三', 'age': 20, 'city': '上海'},{'name': 'tom', 'age': 30, 'city': 'London'}
]# 方式1:用 json.dump() 直接写入(推荐)
with open(r'.\data\users.json', mode='w', encoding='utf-8') as f:json.dump(user_list,f,ensure_ascii=False,  # 显示中文indent=2             # 美化格式)
print("JSON 数据写入文件完成!")# 方式2:先 dumps() 转字符串,再 write()(等价,略繁琐)
# with open(r'.\data\users2.json', mode='w', encoding='utf-8') as f:
#     js_str = json.dumps(user_list, ensure_ascii=False, indent=2)
#     f.write(js_str)

4.2 从文件反序列化:json.load()

json.load(file_obj) 从文件中读取 JSON 数据并直接转为 Python 数据,等价于 json.loads(file.read()),简化代码。

import json# 方式1:用 json.load() 直接读取(推荐)
with open(r'.\data\users.json', mode='r', encoding='utf-8') as f:py_data = json.load(f)
print("从文件读取的 Python 数据:")
print(py_data)
print("类型:", type(py_data))  # 输出:<class 'list'># 方式2:先 read() 读字符串,再 loads()(等价)
# with open(r'.\data\users.json', mode='r', encoding='utf-8') as f:
#     js_str = f.read()
#     py_data2 = json.loads(js_str)
# print("\n方式2读取:", py_data2)
从文件读取的 Python 数据:
[{'name': '张三', 'age': 20, 'city': '上海'}, {'name': 'tom', 'age': 30, 'city': 'London'}]
类型: <class 'list'>

五、常见问题与解决方案

在 JSON 处理中,初学者常遇到中文乱码、特殊类型报错等问题,以下是高频问题的解决方法。

5.1 中文乱码(\uXXXX 转义)

问题:序列化含中文的数据时,输出为 \u5f20\u4e09 等转义字符,而非中文。
原因json.dumps() 默认 ensure_ascii=True,会将非 ASCII 字符转义。
解决:设置 ensure_ascii=False,并指定文件编码为 utf-8(写入文件时)。

# 正确示例
data = {'name': '李四', 'age': 25}
js = json.dumps(data, ensure_ascii=False)
print(js)  # 输出:{"name":"李四","age":25}(中文正常显示)

5.2 特殊类型序列化报错(TypeError

问题:序列化 set/datetime 等类型时,报错 TypeError: Object of type XXX is not JSON serializable
解决:通过 default 参数指定自定义处理函数,将特殊类型转为 JSON 支持的类型(如 set 转 listdatetime 转字符串),见 3.2 节案例。

5.3 JSON 字符串格式错误(JSONDecodeError

问题:反序列化时,报错 json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
常见原因

  1. JSON 字符串用单引号(如 {'name':'mary'});
  2. 字符串含多余逗号(如 [10, 20, ]);
  3. 文件读取时编码错误(如用 gbk 读取 utf-8 文件)。

解决

  1. 确保 JSON 字符串用双引号;
  2. 检查 JSON 语法(无多余逗号、括号匹配);
  3. 读取文件时指定正确编码(如 encoding='utf-8')。

六、总结

本文覆盖了 Python JSON 处理的全流程,核心要点总结如下:

1. 核心函数

函数功能适用场景
json.dumps()Python 数据 → JSON 字符串内存中数据交互(如接口请求)
json.loads()JSON 字符串 → Python 数据内存中数据解析(如接口响应)
json.dump()Python 数据 → JSON 文件数据持久化(写入配置文件)
json.load()JSON 文件 → Python 数据读取配置文件

2. 关键参数

  • ensure_ascii=False:显示中文,避免转义;
  • indent=N:美化 JSON 格式,便于调试;
  • default=函数:处理 set/datetime 等特殊类型;
  • sort_keys=True:按字典 key 排序,输出更规范。

3. 最佳实践

  1. 处理中文时,始终设置 ensure_ascii=False 并指定 encoding='utf-8'
  2. 写入文件优先用 json.dump(),读取文件优先用 json.load()(简化代码);
  3. 遇到特殊类型时,通过 default 参数自定义处理逻辑,避免直接修改原始数据;
  4. 反序列化前,确保输入是严格的 JSON 格式(双引号、无语法错误)。

掌握这些技巧后,你可以轻松应对前后端数据交互、配置文件读写、跨平台数据传输等场景,JSON 处理将成为你的开发利器。

http://www.dtcms.com/a/349671.html

相关文章:

  • pytest+requests+Python3.7+yaml+Allure+Jenkins+docker实现接口自动化测试
  • k8sday17安全机制
  • flask Celery入门:轻松实现异步任务处理
  • 前端通过node本地转译rtsp流,配合hls实现浏览
  • 【SQL】深入理解MySQL存储过程:从入门到实战
  • CUDA 工具包 13.0 正式发布:开启新一代 GPU 计算的基石!
  • 使用EasyExcel根据模板导出文件
  • QtExcel/QXlsx
  • 深入浅出 Java 多态:从原理到实践的全面解析
  • 【RAGFlow代码详解-5】配置系统
  • 基于深度学习的翻拍照片去摩尔纹在线系统设计与实现
  • UE5 HoudiniPivotPainter1.0使用
  • NFC 滤波网络设计考虑
  • 车载通信架构---通过CANoe做 SOME/IP 模拟的配置例如
  • 库存指标怎么算?一文讲清3大库存分析指标
  • 大数据治理域——离线数据开发
  • 小白成长之路-k8s部署项目(二)
  • Legion Y7000P IRX9 DriveList
  • 【数据可视化-100】使用 Pyecharts 绘制人口迁徙图:步骤与数据组织形式
  • 程序设计---状态机
  • KVM 虚拟化技术与部署
  • ZKmall开源商城多端兼容实践:鸿蒙、iOS、安卓全平台适配的技术路径
  • 朴素贝叶斯学习笔记
  • Selenium框架Java实践截图服务
  • 面向过程与面向对象
  • 了解检验和
  • 四,设计模式-原型模式
  • 设计模式5-代理模式
  • 无锁队列的设计与实现
  • jdbc相关内容