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

用JSONEncoder解决Object of type Color is not JSON serializable报错

用json.dumps无法序列化自定义类型,然后报错Object of type Color is not JSON serializable。经过搜索,找到了解决办法,然后写了一个demo记录于此。

不出意外,它可以直接运行并查看效果。

如果你愿意阅读里面的注释,或许能解决一点你的其他问题。

import dataclasses
import enum
import json


class Color(enum.Enum):
    Red = "FF0000"
    Green = "00FF00"
    Blue = "0000FF"


@dataclasses.dataclass
class TestData:
    color: Color
    vi: int = 0
    vf: float = 0.0
    vs: str = ""


def json_loads(text: str) -> dict:
    """"""
    def as_color(dct: dict):
        """仿写自 https://docs.python.org/zh-cn/3.8/library/json.html 网页的 as_complex 的实现"""
        assert isinstance(dct, dict)
        # 例如 {"__Color__": 1, "Color": "0000FF"}
        if len(dct) == 2 and dct.get(f"__{Color.__name__}__") == 1 and dct.get(Color.__name__) in Color._value2member_map_:
            return Color(dct[Color.__name__])
        return dct

    data: dict = json.loads(
        text,
        object_hook=as_color,
    )

    return data


def json_dumps(data: dict) -> str:
    """"""
    # 我最初搜到了 https://blog.csdn.net/qq_43229040/article/details/112306837
    # 尝试之后报错 TypeError: json_dumps.<locals>.change_type() got an unexpected keyword argument 'skipkeys'
    # 搜索后找到了 https://docs.python.org/zh-cn/3.8/library/json.html 才解决问题,
    # 备注: 在 json_dumps 里写 ColorEncoder 是没问题的,
    # 不要为了对仗而在 json_loads 里实现 ColorDecoder(json.JSONDecoder) 并使用,
    # 你仿照 ColorEncoder 写一个 ColorDecoder 试试就知道了,

    class ColorEncoder(json.JSONEncoder):
        """仿写自 https://docs.python.org/zh-cn/3.8/library/json.html 网页的 ComplexEncoder 的实现"""

        def default(self, obj):
            if isinstance(obj, Color):
                # 例如 {"__Color__": 1, "Color": "0000FF"}
                return {f"__{Color.__name__}__": 1, Color.__name__: obj.value}
            # Let the base class default method raise the TypeError
            return json.JSONEncoder.default(self, obj)

    text: str = json.dumps(
        data,
        cls=ColorEncoder,
    )

    return text


if __name__ == "__main__":
    data1 = TestData(color=Color.Red, vi=3, vf=1.414, vs="string")
    dict1 = data1.__dict__
    print("dict1:", dict1)  # dict1: {'color': <Color.Red: 'FF0000'>, 'vi': 3, 'vf': 1.414, 'vs': 'string'}

    try:
        json.dumps(dict1)
    except Exception as ex:
        print(ex)  # Object of type Color is not JSON serializable

    text1: str = json_dumps(dict1)
    print("text1:", text1)  # text1: {"color": {"__Color__": 1, "Color": "FF0000"}, "vi": 3, "vf": 1.414, "vs": "string"}

    dict2 = json_loads(text1)
    print("dict2:", dict2)  # dict2: {'color': <Color.Red: 'FF0000'>, 'vi': 3, 'vf': 1.414, 'vs': 'string'}

    data2 = TestData(**dict2)
    assert data1 == data2  # 断言通过


http://www.kler.cn/a/500532.html

相关文章:

  • Three.js教程015:全面讲解Three.js的UV与应用
  • 动态规划【打家劫舍】
  • 【物流管理系统 - IDEAJavaSwingMySQL】基于Java实现的物流管理系统导入IDEA教程
  • 【数据结构-堆】2233. K 次增加后的最大乘积
  • 【python】str.upper()、str.join()、stri.strip()用法
  • Java 项目中引入阿里云 OSS SDK
  • Pytorch使用手册-优化 Vision Transformer 模型以用于部署(专题十六)
  • ADB->查看进程并强杀进程
  • 【论文阅读】MAMBA系列学习
  • 小学校园安全用电 防触电设备功能介绍 #电不伤人,电不漏电#
  • 计算机组成原理(九):乘法器
  • 1.CSS的复合选择器
  • 基于Springboot+Vue的仓库管理系统
  • 【轻量级推荐算法框架】‌ReChorus‌ 是一个高效、可扩展的轻量级推荐算法框架
  • JavaScript-一份你的前端入门说明书(计算机专业)
  • 基于 Selenium 实现上海大学校园网自动登录
  • 关于在windows系统中编译ffmpeg并导入到自己项目中这件事
  • Proser:升级为简易的通讯调试助手软件
  • iOS 概述
  • 【Uniapp-Vue3】组合式API中的组件的生命周期函数(钩子函数)
  • Docker挂载配置文件方式运行Nginx
  • 【MySQL】SQL菜鸟教程(二)
  • 探索 Oracle 数据库:核心概念与实践指南