5857

29 分钟

#Python 中使用 JSON

JSON(JavaScript Object Notation)是用于将结构化数据表示为 JavaScript 对象的标准格式,通常用于在网站上表示和传输数据(例如从服务器向客户端发送一些数据,因此可以将其显示在网页上)。 虽然 JSON 源自 JavaScript,但几乎所有编程语言都有存取 JSON 的 API。

在 Python 中,可以使用内置的 json 模块将对象序列化为 JSON 字符串或将 JSON 字符串反序列化为对象。

函数说明
dumps将对象序列化为 str
loads将 str 反列化为对象
dump将对象序列化为 str 并写入文件
laod读取文件中的 str 并反列化为对象

函数说明:

def dumps(obj) -> str: ''' 将对象序列化为 JSON 字符串 :param obj: 要序列化的对象 :return: 序列化后的 JSON 字符串 ''' pass def loads(json_str:str): ''' 将 JSON 字符串反列化为对象 :param json_str: 要反序列化的 JSON 字符串 :return: 反序列化后的对象 ''' pass def dump(obj, fp) -> str: ''' 将对象序列化为 JSON 字符串并存入文件中 :param obj: 要序列化的对象 :param fp: 要写入的字节流 :return: 序列化后的 JSON 字符串 ''' pass def load(fp): ''' 读取文件中的 JSON 字符串并反列化为对象 :param fp: 要读取的字节流 :return: 反序列化后的对象 ''' pass

Python 中的值和 JSON 中的表示方式按照下表的对应关系互相转换:

Python 中的类型JSON 中的表示方法备注
intfloat3.1415926
True/Falsetrue/false
Nonenull
str"hello world"JSON 中必须使用双引号
dict{ "key": value }JSON 中必须使用双引号
listtuple[ value1, value2 ]

示例:

import json # 数据 player_state:dict = { 'name': 'link', 'max_hp': 10, 'current_hp': 7, } # 通过 json.dumps 转换为字符串 with open("save.data", "w", encoding='utf-8') as fp: json.dump(player_state, fp) # ... # 下次启动,通过 json.loads 加载数据 with open("save.data", "r", encoding='utf-8') as fp: backup_state = json.load(fp) # 查看数据 print(backup_state)

>>> Establishing WebAssembly Runtime.

>>> Standby.

Powered by Shift.

#自定义类与 JSON 的转换

如下表所示,JSON 本身只支持少数基本类型,虽然通过它们的组合,能够满足一切数据结构,但使用起来并不方便。

Python 中的类型JSON 中的表示方法备注
intfloat3.1415926
True/Falsetrue/false
Nonenull
str"hello world"JSON 中必须使用双引号
dict{ "key": value }JSON 中必须使用双引号
listtuple[ value1, value2 ]

如果直接尝试序列化一个自定义类的对象,会产生一个 TypeError 的异常。

json.dumpsjson.dump 函数包含一个名为 default 的参数,定义将对象转换为 dict 的函数,然后 json 模块负责将 dict 转换为 JOSN 字符串。

将对象转换为 dict 的函数非常简单,直接返回对象的 __dict__ 属性即可,一行 lambda obj:obj.__dict__ 就能实现。

json.loadsjson.load 函数包含一个名为 object_hook 的参数,定义将 dict 转换为对象的函数,然后 json 模块负责将 JOSN 字符串转换为 dict

实现 dict 转换为对象则相对麻烦,一个较为简单的实现如下:

def make_dict_to_obj(cls): ''' 创建字典转对象的函数 :cls: 对象的类型 :return: 转换函数 ''' def dict_to_obj(dict_data:dict): ''' 将字典转换为对象 :param dict_data: 要转换的字典 :return: 转换后的对象 ''' # 创建一个 cls 类型的对象 obj = cls() # 遍历字典 for key in dict_data: # 将 obj 的 key 属性设为 dict_data[key] setattr(obj, key, dict_data[key]) # 返回对象 return obj # 返回创建的转换函数 return dict_to_obj

这个实现无脑将字典的所有元素都塞给了对象,可能缺少了类需要的属性或包含了类不需要的属性,这通常不是什么问题。

缺少的属性在创建对象时已经设置了初始值,多余的属性通常没有影响,也可以在 setattr 之前通过 hasattr 判断,在实际开发中应当根据实际需求决定处理逻辑。

示例:

import json def make_dict_to_obj(cls): ''' 创建字典转对象的函数 :cls: 对象的类型 :return: 转换函数 ''' def dict_to_obj(dict_data:dict): ''' 将字典转换为对象 :param dict_data: 要转换的字典 :return: 转换后的对象 ''' # 创建一个 cls 类型的对象 obj = cls() # 遍历字典 for key in dict_data: # 将 obj 的 key 属性设为 dict_data[key] setattr(obj, key, dict_data[key]) # 返回对象 return obj # 返回创建的转换函数 return dict_to_obj # 自定义类 class PlayerState: def __init__(self): self.name = 'link' self.max_hp = 10 self.current_hp = 7 # 创建对象 player_state = PlayerState() # 修改属性值 player_state.name = 'zelda' player_state.max_hp = 20 player_state.current_hp = 2 # 序列化为 JSON 字符串 json_str:str = json.dumps(player_state, default=lambda obj:obj.__dict__) # 通过 __dict__ 属性返回对象的字典 print(json_str) # 反序列化为对象 backup_state = json.loads(json_str, object_hook=make_dict_to_obj(PlayerState)) # 通过 make_dict_to_obj 创建字典到类的转换函数 print(backup_state.name) print(backup_state.max_hp) print(backup_state.current_hp)

>>> Establishing WebAssembly Runtime.

>>> Standby.

Powered by Shift.

如果完全不需要考虑字段的缺失和冗余,转换函数还有一种更简单的写法,通过内置函数 type 创建对象。

def dict_to_obj(dict_data:dict): ''' 将字典转换为对象 :param dict_data: 要转换的字典 :return: 转换后的对象 ''' # 创建并返回一个自定义对象 return type('CustomType', (), dict_data)

示例:

import json def dict_to_obj(dict_data:dict): ''' 将字典转换为对象 :param dict_data: 要转换的字典 :return: 转换后的对象 ''' # 创建并返回一个自定义对象 return type('CustomType', (), dict_data) # 自定义类 class PlayerState: def __init__(self): self.name = 'link' self.max_hp = 10 self.current_hp = 7 # 创建对象 player_state = PlayerState() # 修改属性值 player_state.name = 'zelda' player_state.max_hp = 20 player_state.current_hp = 2 # 序列化为 JSON 字符串 json_str:str = json.dumps(player_state, default=lambda obj:obj.__dict__) # 通过 __dict__ 属性返回对象的字典 print(json_str) # 反序列化为对象 backup_state = json.loads(json_str, object_hook=dict_to_obj) # 通过 dict_to_obj 将字典转换为对象 print(backup_state.name) print(backup_state.max_hp) print(backup_state.current_hp)

>>> Establishing WebAssembly Runtime.

>>> Standby.

Powered by Shift.

创建于 2025/6/6

更新于 2025/6/6