Python数据类转换为JSON的常用方法总结

Written by

in

文章目录
  • 先定义一个典型的嵌套数据类,作为后续转换的示例: from dataclasses import dataclass, asdict import json from datetime import datetime # 包含非基础类型,模拟真实场景 # 嵌套子数据类 @dataclass class Address: province: str city: str detail: str = “” # 可选字段 # 主数据类 @dataclass class User: id: int name: str age: int register_time: datetime # 非JSON原生类型 address: Address # 嵌套数据类 tags: list[str] = None # 可选列表字段 # 创建测试实例 test_user = User( id=1001, name=”张三”, age=28, register_time=datetime(2026, 1, 19, 10, 30), address=Address(province=”浙江省”, city=”杭州市”, detail=”西湖区XX路”), tags=[“VIP”, “新用户”] )
  • 这是最基础的优雅方式,利用dataclasses内置的asdict方法将数据类转成字典,再用json.dumps序列化。
  • 如果有多个数据类需要转换,手动处理非基础类型会很繁琐,推荐自定义JSONEncoder,实现统一的序列化规则。
  • 将转换逻辑封装成工具函数,一键调用,适合项目中多处使用的场景: def dataclass_to_json(obj, indent=2): “”” 数据类转JSON字符串的工具函数 :param obj: 数据类实例(支持嵌套) :param indent: 格式化缩进,None表示紧凑输出 :return: JSON字符串 “”” return json.dumps( obj, cls=DataclassJSONEncoder, ensure_ascii=False, indent=indent ) # 调用示例(一行搞定) user_json = dataclass_to_json(test_user) print(user_json)
  • 如果你的场景需要数据验证 + 优雅序列化,推荐直接使用pydantic(Python 生态中最主流的数据验证库),它的BaseModel比原生dataclass更强大,且原生支持 JSON 转换。
  • 简单场景:用dataclasses.asdict + json.dumps,手动处理非基础类型,快速实现; 通用场景:自定义JSONEncoder,统一管理序列化规则,适合多个数据类的项目; 生产环境:优先使用pydantic.BaseModel,兼顾数据验证和优雅序列化,减少冗余代码; 核心原则:避免手动拼接字典,利用内置工具 / 成熟库实现转换,保证代码的可维护性和扩展性。 以上就是Python数据类转换为JSON的常用方法总结的详细内容,更多关于Python数据类转JSON的资料请关注风君子博客其它相关文章! 您可能感兴趣的文章: 将Python数据类转换为JSON的三种方法 将Python数据类优雅地转换为JSON的方法详解 Python中数据类转换为JSON的方法详解 Python xml、字典、json、类四种数据类型如何实现互相转换
  • 目录
    • 前置准备:定义测试数据类
    • 方法 1:基础版 -dataclasses.asdict手动转换(简单场景)
      • 代码实现:
      • 输出结果:
      • 关键解释:
    • 方法 2:进阶版 – 自定义JSONEncoder(通用可扩展)
      • 代码实现:
      • 关键解释:
    • 方法 3:优化版 – 封装成工具函数(复用性拉满)
      • 方法 4:高级版 – 使用pydantic(生产环境推荐)
        • 前置依赖:
        • 代码实现:
        • 输出结果(时间格式自定义后):
        • 关键优势:
      • 总结

        Python 标准库的json模块默认无法直接序列化自定义的dataclass实例(会报Object of type XXX is not JSON serializable),核心原因是json只支持基础类型(str/int/list/dict 等)。下面我会从基础到进阶给出 4 种优雅的转换方法,覆盖简单场景到生产级复杂场景,你可根据需求选择。

        先定义一个典型的嵌套数据类,作为后续转换的示例:

        from dataclasses import dataclass, asdict
        import json
        from datetime import datetime  # 包含非基础类型,模拟真实场景
        
        # 嵌套子数据类
        @dataclass
        class Address:
            province: str
            city: str
            detail: str = ""  # 可选字段
        
        # 主数据类
        @dataclass
        class User:
            id: int
            name: str
            age: int
            register_time: datetime  # 非JSON原生类型
            address: Address  # 嵌套数据类
            tags: list[str] = None  # 可选列表字段
        
        # 创建测试实例
        test_user = User(
            id=1001,
            name="张三",
            age=28,
            register_time=datetime(2026, 1, 19, 10, 30),
            address=Address(province="浙江省", city="杭州市", detail="西湖区XX路"),
            tags=["VIP", "新用户"]
        )
        

        这是最基础的优雅方式,利用dataclasses内置的asdict方法将数据类转成字典,再用json.dumps序列化。

        # 步骤1:将dataclass转成普通字典
        user_dict = asdict(test_user)
        # 步骤2:处理非JSON原生类型(如datetime)
        user_dict["register_time"] = user_dict["register_time"].isoformat()
        
        # 步骤3:序列化为JSON字符串
        user_json = json.dumps(user_dict, ensure_ascii=False, indent=2)
        print(user_json)
        

        {
          "id": 1001,
          "name": "张三",
          "age": 28,
          "register_time": "2026-01-19T10:30:00",
          "address": {
            "province": "浙江省",
            "city": "杭州市",
            "detail": "西湖区XX路"
          },
          "tags": ["VIP", "新用户"]
        }
        

        • asdict(test_user):核心函数,将数据类实例递归转换为普通字典(嵌套的Address也会被转成字典);
        • ensure_ascii=False:保留中文等非 ASCII 字符,避免转成uXXXX编码;
        • indent=2:格式化输出,提升可读性;
        • 需手动处理datetime等非 JSON 原生类型(JSON 仅支持字符串 / 数字 / 布尔 / 列表 / 字典 /null)。

        如果有多个数据类需要转换,手动处理非基础类型会很繁琐,推荐自定义JSONEncoder,实现统一的序列化规则

        class DataclassJSONEncoder(json.JSONEncoder):
            """自定义JSON编码器,支持dataclass和常见非基础类型"""
            def default(self, obj):
                # 第一步:处理dataclass实例
                if hasattr(obj, "__dataclass_fields__"):  # 判断是否是dataclass
                    return asdict(obj)
                # 第二步:处理datetime类型
                if isinstance(obj, datetime):
                    return obj.isoformat()
                # 第三步:其他类型交给父类处理(会抛出标准异常)
                return super().default(obj)
        
        # 直接使用自定义编码器序列化
        user_json = json.dumps(
            test_user,
            cls=DataclassJSONEncoder,  # 指定自定义编码器
            ensure_ascii=False,
            indent=2
        )
        print(user_json)
        

        • 继承json.JSONEncoder并重写default方法:这是json模块扩展序列化规则的标准方式;
        • __dataclass_fields__:dataclass 实例的内置属性,用于判断是否为数据类;
        • 可扩展:如需支持date/UUID等类型,只需在default方法中新增isinstance判断即可;
        • 无需手动转字典,直接序列化数据类实例,代码更简洁。

        将转换逻辑封装成工具函数,一键调用,适合项目中多处使用的场景:

        def dataclass_to_json(obj, indent=2):
            """
            数据类转JSON字符串的工具函数
            :param obj: 数据类实例(支持嵌套)
            :param indent: 格式化缩进,None表示紧凑输出
            :return: JSON字符串
            """
            return json.dumps(
                obj,
                cls=DataclassJSONEncoder,
                ensure_ascii=False,
                indent=indent
            )
        
        # 调用示例(一行搞定)
        user_json = dataclass_to_json(test_user)
        print(user_json)
        

        如果你的场景需要数据验证 + 优雅序列化,推荐直接使用pydantic(Python 生态中最主流的数据验证库),它的BaseModel比原生dataclass更强大,且原生支持 JSON 转换。

        pip install pydantic
        

        from pydantic import BaseModel
        from datetime import datetime
        
        # 替换原生dataclass为pydantic.BaseModel
        class Address(BaseModel):
            province: str
            city: str
            detail: str = ""
        
        class User(BaseModel):
            id: int
            name: str
            age: int
            register_time: datetime
            address: Address
            tags: list[str] = None
        
            # 可选:自定义JSON序列化配置(如datetime格式)
            class Config:
                json_encoders = {
                    datetime: lambda v: v.strftime("%Y-%m-%d %H:%M:%S")  # 自定义时间格式
                }
        
        # 创建实例(pydantic会自动验证字段类型)
        test_user = User(
            id=1001,
            name="张三",
            age=28,
            register_time=datetime(2026, 1, 19, 10, 30),
            address=Address(province="浙江省", city="杭州市", detail="西湖区XX路"),
            tags=["VIP", "新用户"]
        )
        
        # 原生支持JSON转换(一行搞定)
        user_json = test_user.json(ensure_ascii=False, indent=2)
        print(user_json)
        

        {
          "id": 1001,
          "name": "张三",
          "age": 28,
          "register_time": "2026-01-19 10:30:00",
          "address": {
            "province": "浙江省",
            "city": "杭州市",
            "detail": "西湖区XX路"
          },
          "tags": ["VIP", "新用户"]
        }
        

        • 原生支持json()方法:无需手动写编码器,开箱即用;
        • 自动数据验证:创建实例时会校验字段类型(如age传字符串会直接报错);
        • 灵活配置:通过Config.json_encoders自定义非基础类型的序列化规则;
        • 支持嵌套、可选字段、默认值等,完全兼容原生 dataclass 的用法,且功能更强。

        1. 简单场景:用dataclasses.asdict + json.dumps,手动处理非基础类型,快速实现;
        2. 通用场景:自定义JSONEncoder,统一管理序列化规则,适合多个数据类的项目;
        3. 生产环境:优先使用pydantic.BaseModel,兼顾数据验证和优雅序列化,减少冗余代码;
        4. 核心原则:避免手动拼接字典,利用内置工具 / 成熟库实现转换,保证代码的可维护性和扩展性。

        以上就是Python数据类转换为JSON的常用方法总结的详细内容,更多关于Python数据类转JSON的资料请关注风君子博客其它相关文章!

        您可能感兴趣的文章:

        • 将Python数据类转换为JSON的三种方法
        • 将Python数据类优雅地转换为JSON的方法详解
        • Python中数据类转换为JSON的方法详解
        • Python xml、字典、json、类四种数据类型如何实现互相转换

        站内搜索