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

Python--JSON格式

一、基础:JSON 与 Python 数据类型的对应关系

JSON 仅支持有限的数据类型,与 Python 类型的对应关系如下(核心基础,必须掌握):

Python 类型JSON 类型说明
dictobject键必须为字符串(JSON 要求)
list/tuplearray元组序列化后会转为列表
strstring必须为 Unicode 字符串
int/floatnumber整数 / 浮点数直接对应
Truetrue布尔值对应
Falsefalse布尔值对应
Nonenull空值对应

注意:JSON 不支持 Python 的setdatetime自定义类等类型,需特殊处理(见后文)

补充:

字符串与Unicode字符串的区别

  1. 存储的内容不同

    • Unicode 字符串:存储的是 Unicode 码点(code point),即字符的抽象数字表示(例如,汉字 “中” 的 Unicode 码点是 U+4E2D)。它不依赖于具体的编码方式(如 UTF-8、UTF-16 等),而是直接代表字符本身。
    • 普通字符串(字节字符串):存储的是原始字节(0-255 的整数),这些字节需要通过特定编码(如 ASCII、UTF-8、GBK 等)才能解析为有意义的字符。
  2. 编码依赖性不同

    • Unicode 字符串:与编码方式无关,是 “字符的抽象序列”。例如,在 Python 中,str 类型就是 Unicode 字符串,无论字符是中文、英文还是其他语言,都统一用 Unicode 码点表示。
    • 普通字符串:依赖于编码方式。同样的字节序列,用不同编码解析可能得到完全不同的字符。例如,字节 0xE4 0xB8 0xAD 用 UTF-8 解析是 “中”,但用其他编码解析可能是乱码。
  3. 支持的字符范围不同

    • Unicode 字符串:支持全球所有语言的字符(包括 emoji),因为 Unicode 标准包含了几乎所有已知的字符集。
    • 普通字符串(如基于 ASCII 编码):仅支持有限字符(如英文字母、数字和部分符号),无法直接表示中文、日文等复杂字符。
  4. 在编程语言中的表现

    • 例如在 Python 中:
      • str 类型是 Unicode 字符串(如 s = "中")。
      • bytes 类型是字节字符串(如 b = b"\xe4\xb8\xad",是 “中” 的 UTF-8 编码字节)。
    • 两者需要通过编码(str.encode(encoding))或解码(bytes.decode(encoding))进行转换。

      简单来说,Unicode 字符串是 “字符的抽象表示”,而普通字符串(字节串)是 “字符的具体编码字节”。理解两者的区别是处理多语言文本的基础,可避免常见的乱码问题。

二、核心操作:序列化与反序列化

1. 序列化(Python 对象→JSON)
  • json.dumps(obj):将 Python 对象转为 JSON 字符串
  • json.dump(obj, file):将 Python 对象直接写入文件(推荐,避免手动处理文件关闭)
import json# 定义Python对象
data = {"name": "Alice","age": 30,"is_student": False,"hobbies": ["reading", "coding"],"address": None,"scores": (90.5, 85, 95)  # 元组会转为JSON数组
}# 1. 转为JSON字符串
json_str = json.dumps(data)
print("JSON字符串:", json_str)# 2. 直接写入文件(最佳实践:用with语句)
with open("data.json", "w", encoding="utf-8") as f:json.dump(data, f, ensure_ascii=False)  # ensure_ascii=False:保留中文原样

运行结果:

2. 反序列化(JSON→Python 对象)
  • json.loads(json_str):将 JSON 字符串转为 Python 对象
  • json.load(file):从文件读取 JSON 并转为 Python 对象(推荐)
import json
import osdef main():# 1. 从JSON字符串解析json_str = '{"name": "Bob", "age": 25, "hobbies": ["gaming"]}'try:data = json.loads(json_str)print("1. 字符串解析结果:", data)print("   数据类型:", type(data))  # 输出字典类型print("   姓名:", data["name"])print("   年龄:", data["age"])print("   爱好:", data["hobbies"][0])except json.JSONDecodeError as e:print("字符串解析错误:", e)# 2. 从文件读取(包含文件创建逻辑,确保文件存在)file_name = "data.json"# 检查文件是否存在,不存在则创建并写入示例数据if not os.path.exists(file_name):print(f"\n检测到'{file_name}'不存在,正在创建示例文件...")sample_data = {"name": "Alice", "age": 30, "city": "New York"}with open(file_name, "w", encoding="utf-8") as f:json.dump(sample_data, f, ensure_ascii=False, indent=2)print(f"示例文件'{file_name}'创建成功")# 从文件读取JSON数据try:with open(file_name, "r", encoding="utf-8") as f:data_from_file = json.load(f)print("\n2. 文件读取结果:", data_from_file)print("   从文件获取的姓名:", data_from_file["name"])print("   从文件获取的城市:", data_from_file["city"])except FileNotFoundError:print(f"文件读取错误:'{file_name}'未找到")except json.JSONDecodeError as e:print(f"文件内容解析错误:", e)except KeyError as e:print(f"数据键不存在:", e)if __name__ == "__main__":main()

运行结果:

三、进阶:处理复杂数据类型(datetime、自定义类等)

JSON 默认不支持 Python 的datetimeset自定义类等类型,直接序列化会报错。解决方法:自定义编码器 / 解码器

1. 处理 datetime 对象
from datetime import datetime
import json# 定义含datetime的对象
data = {"event": "会议","start_time": datetime(2023, 10, 1, 9, 30),"end_time": datetime(2023, 10, 1, 11, 0)
}# 方法1:自定义序列化函数(推荐简单场景)
def datetime_serializer(obj):if isinstance(obj, datetime):return obj.isoformat()  # 转为ISO格式字符串(如"2023-10-01T09:30:00")raise TypeError(f"类型 {type(obj)} 不支持序列化")# 序列化时指定default参数
json_str = json.dumps(data, default=datetime_serializer, ensure_ascii=False)
print("含datetime的JSON:", json_str)# 反序列化时还原为datetime
def datetime_decoder(dct):for key, value in dct.items():if key.endswith("_time"):  # 假设时间字段以_time结尾try:dct[key] = datetime.fromisoformat(value)except ValueError:pass  # 非时间格式不处理return dctdata_restored = json.loads(json_str, object_hook=datetime_decoder)
print("还原的start_time:", data_restored["start_time"], type(data_restored["start_time"]))  # <class 'datetime.datetime'>

 运行结果:

2. 处理自定义类
import jsonclass User:def __init__(self, name, age):self.name = nameself.age = age# 实例化
user = User("Charlie", 28)# 方法2:继承JSONEncoder实现自定义编码器(适合复杂场景)
class UserEncoder(json.JSONEncoder):def default(self, obj):if isinstance(obj, User):# 转为字典(包含类标识,便于反序列化)return {"__class__": "User", "name": obj.name, "age": obj.age}return super().default(obj)  # 其他类型用默认处理# 序列化
json_str = json.dumps(user, cls=UserEncoder, ensure_ascii=False)
print("User序列化:", json_str)  # {"__class__": "User", "name": "Charlie", "age": 28}# 反序列化时还原为User对象
def user_decoder(dct):if "__class__" in dct and dct["__class__"] == "User":return User(dct["name"], dct["age"])return dctuser_restored = json.loads(json_str, object_hook=user_decoder)
print("还原的User:", user_restored.name, user_restored.age)  # Charlie 28

运行结果:

四、错误处理:捕获 JSON 操作中的异常

JSON 处理中常见异常:

  • json.JSONDecodeError:JSON 格式错误(如括号不匹配、语法错误)
  • TypeError:序列化不支持的类型(未自定义处理时)

最佳实践:强制捕获异常

代码:

import json# 示例1:处理JSON格式错误
bad_json = '{"name": "Alice", age: 30}'  # 错误:age未加引号
try:data = json.loads(bad_json)
except json.JSONDecodeError as e:print(f"JSON格式错误:{e},位置:{e.pos}")  # 提示错误位置# 示例2:处理不支持的类型
data = {"set": {1, 2, 3}}  # set不支持序列化
try:json.dumps(data)
except TypeError as e:print(f"序列化错误:{e}")  # 提示"Object of type set is not JSON serializable"

运行结果

JSON格式错误:Expecting property name enclosed in double quotes: line 1 column 19 (char 18),位置:18
序列化错误:Object of type set is not JSON serializable

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

相关文章:

  • 艺术性与真实感并存:FLUX.1 Krea [dev] 开源模型速览
  • 复杂环境跌倒识别准确率↑31%!陌讯多模态算法在智慧养老的落地实践
  • 嵌入式硬件中运放内部底层分析
  • Java、Android及计算机基础面试题总结
  • Salesforce Hub-Spoke 架构介绍
  • LoRa基站和网关的区别
  • C++-特殊类设计
  • 学习游戏制作记录(将各种属性应用于战斗以及实体的死亡)8.5
  • 生物医药科研革命:深度解析协同实验记录如何重塑新药研发全流程
  • 应急响应实验复现
  • 浅谈 NUMA 与 MySQL
  • MySQL 在麒麟系统上部署使用 + DBeaver 远程连接 + SQL 数据导入完整流程
  • 华为云代理商的作用与价值解析
  • 嵌套路由配置(React-Router5)
  • Android原生项目集成Flutter模块极简指南
  • 使用buildx构建镜像
  • 若依前后端分离版学习笔记(五)——Spring Boot简介与Spring Security
  • [驱动开发篇] Can通信进阶 --- CanFD 的三次采样
  • Chisel芯片开发入门系列 -- 18. CPU芯片开发和解释8(流水线架构的代码级理解)
  • 深度学习-卷积神经网络CNN-填充与步幅
  • AR文旅新纪元:从黄姚古镇到秦始皇陵,虚实共生的沉浸式体验革命
  • 华为云云产品的发展趋势:技术创新驱动数字化未来
  • 基于Docker的RabbitMQ运行参数设置
  • 基于华为开发者空间的Open WebUI数据分析与可视化实战
  • 光伏清洗机器人是什么?艾利特协作机器人如何重塑新能源运维效率
  • 【18】C实战篇——C语言 文件读写【fputc、fgetc、fputs、fgets】
  • FPGA学习笔记——简易的DDS信号发生器
  • 力扣106:从中序与后序遍历序列构造二叉树
  • Android 之 Kotlin 和 MVVM 架构的 Android 登录示例
  • 宝塔(免费版9.2.0)的docker拉取仓库失败的加速方法