国际访客建议访问 Primers 编程伙伴 国际版站点 > Python 教程 > JSON 以获得更好的体验。

# 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 中的表示方法 备注
intfloat 3.1415926
True/False true/false
None null
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)

# 自定义类与 JSON 的转换

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

Python 中的类型 JSON 中的表示方法 备注
intfloat 3.1415926
True/False true/false
None null
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)

如果完全不需要考虑字段的缺失和冗余,转换函数还有一种更简单的写法,通过内置函数 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)
本文 更新于: 2025-11-27 09:37:57 创建于: 2025-11-27 09:37:57