autogen_core中的DataclassJsonMessageSerializer类
源代码
import json
from dataclasses import asdict, dataclass, fields
from typing import Any, ClassVar, Dict, List, Protocol, Sequence, TypeVar, cast, get_args, get_origin, runtime_checkable, Union
from pydantic import BaseModelfrom types import NoneType, UnionTypedef _type_name(cls: type[Any] | Any) -> str:if isinstance(cls, type):return cls.__name__else:return cast(str, cls.__class__.__name__)def is_union(t: object) -> bool:origin = get_origin(t)return origin is Union or origin is UnionTypeT = TypeVar("T")class MessageSerializer(Protocol[T]):@propertydef data_content_type(self) -> str: ...@propertydef type_name(self) -> str: ...def deserialize(self, payload: bytes) -> T: ...def serialize(self, message: T) -> bytes: ...@runtime_checkable
class IsDataclass(Protocol):# as already noted in comments, checking for this attribute is currently# the most reliable way to ascertain that something is a dataclass__dataclass_fields__: ClassVar[Dict[str, Any]]def is_dataclass(cls: type[Any]) -> bool:return hasattr(cls, "__dataclass_fields__")def has_nested_dataclass(cls: type[IsDataclass]) -> bool:# iterate fields and check if any of them are dataclassesreturn any(is_dataclass(f.type) for f in cls.__dataclass_fields__.values())def contains_a_union(cls: type[IsDataclass]) -> bool:return any(is_union(f.type) for f in cls.__dataclass_fields__.values())def has_nested_base_model(cls: type[IsDataclass]) -> bool:for f in fields(cls):field_type = f.type# Resolve forward references and other annotationsorigin = get_origin(field_type)args = get_args(field_type)# If the field type is directly a subclass of BaseModelif isinstance(field_type, type) and issubclass(field_type, BaseModel):return True# If the field type is a generic type like List[BaseModel], Tuple[BaseModel, ...], etc.if origin is not None and args:for arg in args:# Recursively check the argument typesif isinstance(arg, type) and issubclass(arg, BaseModel):return Trueelif get_origin(arg) is not None:# Handle nested generics like List[List[BaseModel]]if has_nested_base_model_in_type(arg):return True# Handle Union typeselif args:for arg in args:if isinstance(arg, type) and issubclass(arg, BaseModel):return Trueelif get_origin(arg) is not None:if has_nested_base_model_in_type(arg):return Truereturn Falsedef has_nested_base_model_in_type(tp: Any) -> bool:"""Helper function to check if a type or its arguments is a BaseModel subclass."""origin = get_origin(tp)args = get_args(tp)if isinstance(tp, type) and issubclass(tp, BaseModel):return Trueif origin is not None and args:for arg in args:if has_nested_base_model_in_type(arg):return Truereturn FalseDataclassT = TypeVar("DataclassT", bound=IsDataclass)JSON_DATA_CONTENT_TYPE = "application/json"
"""JSON data content type"""# TODO: what's the correct content type? There seems to be some disagreement over what it should be
PROTOBUF_DATA_CONTENT_TYPE = "application/x-protobuf"
"""Protobuf data content type"""class DataclassJsonMessageSerializer(MessageSerializer[DataclassT]):def __init__(self, cls: type[DataclassT]) -> None:if contains_a_union(cls):raise ValueError("Dataclass has a union type, which is not supported. To use a union, use a Pydantic model")if has_nested_dataclass(cls) or has_nested_base_model(cls):raise ValueError("Dataclass has nested dataclasses or base models, which are not supported. To use nested types, use a Pydantic model")self.cls = cls@propertydef data_content_type(self) -> str:return JSON_DATA_CONTENT_TYPE@propertydef type_name(self) -> str:return _type_name(self.cls)def deserialize(self, payload: bytes) -> DataclassT:message_str = payload.decode("utf-8")return self.cls(**json.loads(message_str))def serialize(self, message: DataclassT) -> bytes:return json.dumps(asdict(message)).encode("utf-8")
代码解释
这段代码定义了一个用于序列化和反序列化数据类(dataclass)和 Pydantic 模型的序列化器,特别是针对 JSON 格式。它的目标是提供一种结构化的方式来序列化和反序列化消息,并检查不支持的特性,例如嵌套的数据类、嵌套的 Pydantic 模型以及数据类中联合类型(union type)。
1. 导入
import json
from dataclasses import asdict, dataclass, fields
from typing import Any, ClassVar, Dict, List, Protocol, Sequence, TypeVar, cast, get_args, get_origin, runtime_checkable, Union
from pydantic import BaseModelfrom types import NoneType, UnionType
这部分导入了必要的模块:
json: 用于 JSON 序列化/反序列化。dataclasses: 用于处理数据类 (asdict,dataclass,fields)。typing: 用于类型提示和处理泛型 (Any,ClassVar,Dict,List,Protocol,Sequence,TypeVar,cast,get_args,get_origin,runtime_checkable,Union)。pydantic: 用于处理 Pydantic 模型 (BaseModel)。types: 用于处理类型提示,包括NoneType和UnionType。
2. 辅助函数
_type_name(cls): 返回类或对象的名称。is_union(t): 检查类型t是否为Union或UnionType。is_dataclass(cls): 检查类cls是否为数据类。has_nested_dataclass(cls): 检查数据类cls是否包含任何嵌套的数据类作为字段。contains_a_union(cls): 检查数据类cls是否包含任何Union类型作为字段类型。has_nested_base_model(cls): 检查数据类cls是否包含任何嵌套的 PydanticBaseModel子类作为字段,包括处理List[BaseModel]等泛型和嵌套泛型。has_nested_base_model_in_type(tp):has_nested_base_model使用的辅助函数,用于递归检查类型或其参数是否为BaseModel子类。
3. 类型变量和常量
T: 一个泛型类型变量。DataclassT: 绑定到IsDataclass的类型变量。JSON_DATA_CONTENT_TYPE: JSON 内容类型的常量。PROTOBUF_DATA_CONTENT_TYPE: Protobuf 内容类型的常量(虽然在 JSON 序列化器中未使用)。
4. MessageSerializer 协议
class MessageSerializer(Protocol[T]):@propertydef data_content_type(self) -> str: ...@propertydef type_name(self) -> str: ...def deserialize(self, payload: bytes) -> T: ...def serialize(self, message: T) -> bytes: ...
定义了消息序列化器的协议(接口)。任何实现此协议的类都必须定义指定的属性和方法:
data_content_type: 序列化数据的 MIME 类型。type_name: 被序列化类型的名称。deserialize(payload): 将字节负载反序列化为T类型的对象。serialize(message): 将T类型的对象序列化为字节负载。
5. IsDataclass 协议
@runtime_checkable
class IsDataclass(Protocol):__dataclass_fields__: ClassVar[Dict[str, Any]]
一个运行时可检查的协议,用于确定类是否为数据类。它检查 __dataclass_fields__ 属性是否存在。
6. DataclassJsonMessageSerializer 类
class DataclassJsonMessageSerializer(MessageSerializer[DataclassT]):# ...
此类实现了 MessageSerializer 协议,用于数据类的 JSON 序列化。
__init__(self, cls): 构造函数,它接受数据类类型cls作为参数。它执行关键检查:- 如果数据类包含
Union类型,则引发ValueError(使用 Pydantic 处理联合类型)。 - 如果数据类包含嵌套的数据类或 Pydantic 模型,则引发
ValueError(使用 Pydantic 处理嵌套类型)。
- 如果数据类包含
data_content_type属性:返回JSON_DATA_CONTENT_TYPE。type_name属性:返回数据类的名称。deserialize(payload): 将 JSON 负载反序列化为数据类的实例。serialize(message): 将数据类实例序列化为 JSON 负载。
总结
这段代码提供了一个专门用于简单数据类(没有联合或嵌套的数据类/模型)的 JSON 序列化器。它强调使用 Pydantic 来处理更复杂的场景,从而实现了清晰的关注点分离,并使序列化过程更具可预测性。这是一种很好的方法,可以避免直接在数据类中泛型序列化嵌套结构和联合类型的复杂性。
几个例子
@dataclass
class Point:x: inty: intserializer = DataclassJsonMessageSerializer(Point)point = Point(x=10, y=20)
serialized_data = serializer.serialize(point)
print(f"Serialized data: {serialized_data}") # Output: b'{"x": 10, "y": 20}'deserialized_point = serializer.deserialize(serialized_data)
print(f"Deserialized point: {deserialized_point}") # Output: Point(x=10, y=20)print(isinstance(deserialized_point, Point)) # Output: True
Serialized data: b'{"x": 10, "y": 20}'
Deserialized point: Point(x=10, y=20)
True
@dataclass
class Line:points: list[Point]line = Line(points=[Point(x=1, y=2), Point(x=3, y=4)])
serializer_line = DataclassJsonMessageSerializer(Line)serialized_line = serializer_line.serialize(line)
print(f"Serialized line: {serialized_line}") # Output: b'{"points": [{"x": 1, "y": 2}, {"x": 3, "y": 4}]}'deserialized_line = serializer_line.deserialize(serialized_line)
print(f"Deserialized line: {deserialized_line}") # Output: Line(points=[Point(x=1, y=2), Point(x=3, y=4)])print(isinstance(deserialized_line, Line)) # Output: True
Serialized line: b'{"points": [{"x": 1, "y": 2}, {"x": 3, "y": 4}]}'
Deserialized line: Line(points=[{'x': 1, 'y': 2}, {'x': 3, 'y': 4}])
True
@dataclass
class Rectangle:top_left: Pointbottom_right: Point# 这会抛出 ValueError,因为 Rectangle 包含嵌套的数据类 Point
try:serializer_rectangle = DataclassJsonMessageSerializer(Rectangle)
except ValueError as e:print(f"Error: {e}") # Output: Error: Dataclass has nested dataclasses or base models, which are not supported. To use nested types, use a Pydantic model
Error: Dataclass has nested dataclasses or base models, which are not supported. To use nested types, use a Pydantic model
from typing import Union@dataclass
class Shape:shape_type: Union[str, int]try:serializer_shape = DataclassJsonMessageSerializer(Shape)
except ValueError as e:print(f"Error: {e}") # Output: Error: Dataclass has a union type, which is not supported. To use a union, use a Pydantic model
Error: Dataclass has a union type, which is not supported. To use a union, use a Pydantic model
相关文章:
autogen_core中的DataclassJsonMessageSerializer类
源代码 import json from dataclasses import asdict, dataclass, fields from typing import Any, ClassVar, Dict, List, Protocol, Sequence, TypeVar, cast, get_args, get_origin, runtime_checkable, Union from pydantic import BaseModelfrom types import NoneType, …...
floodfill算法系列一>太平洋大西洋水流问题
目录 题目方法解析:代码设计:代码呈现: 题目方法解析: 代码设计: 代码呈现: class Solution {int m,n;int[] dx {0,0,-1,1};int[] dy {-1,1,0,0};public List<List<Integer>> pacificAtlant…...
DeepSeek 助力 Vue 开发:打造丝滑的无限滚动(Infinite Scroll)
前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 目录 Deep…...
JavaScript 内置对象-Math对象
在JavaScript中,Math 对象提供了一系列与数学相关的静态方法和属性,帮助开发者执行复杂的计算任务。无论是简单的算术运算还是高级的几何、统计计算,Math 对象都能提供强大的支持。本文将详细介绍 Math 对象的主要功能及其使用方法。 一、简…...
硕成C语言22【一些算法和数组的概念】
1.求水仙花数 #include <stdio.h>int main() {//求水仙花数:1.三位数 2.个位的立方十位的立方百位的立方该数int unit, tens, hundreds;for (int i 100; i < 1000; i)//i表示该水仙花数{unit i / 1 % 10;tens i / 10 % 10;hundreds i / 100 % 10;if (…...
Halcon相机标定
1,前言。 相机的成像过程实质上是坐标系的转换。首先空间中的点由“世界坐标系”转换到“相机坐标系”,然后再将其投影到成像平面(图像物理坐标系),最后再将成像的平面上的数据转换为图像像素坐标系。但是由于透镜的制…...
部门管理(体验,最原始方法来做,Django+mysql)
本人初学,写完代码在此记录和复盘 在创建和注册完APP之后(我的命名是employees),编写models.py文件创建表 手动插入了几条数据 1.部门查询 urls.py和views.py在编写之前,都要注意导入对应的库 urls.py:…...
clickhouse集群搭建
Clickhouse集群搭建 文章目录 Clickhouse集群搭建安装包下载clickhouse单机安装默认安装默认数据库目录更改默认数据目录 2分片-1副本-3节点集群搭建1. 配置hosts2. 修改每个主机的主机名3. 配置文件上传配置文件分布chnode1配置文件chnode2配置文件chnode3配置文件 4. 重启cli…...
250214-java类集框架
单列集合是list和set,list的实现类有ArrayList和LinkedList,前者是数组实现,后者是链表实现。list和set,前者有序、可重复,后者无序不可重复。 1.单列集合 1.1. list java.util.List接口继承自Collection接口&#…...
二叉树(C语言版)
文章目录 二叉树完全二叉树和满二叉树二叉搜索树基本操作实现代码运行结果 分析红黑树2-3-4树(理论模型)红黑树(实际实现) 二叉树 树是一种层次结构,它在现实生活中是广泛存在的,比如:族谱(family tree),组织机构,目录…...
ASP.NET Core 面试宝典【刷题系列】
文章目录 引言1、什么是 dot net core 的 startup class?2、什么是中间件?3、application builder 的 use 和 run 方法有什么区别?4、dot net core 管道里面的map拓展有什么作用?5、dot net core 里面的路径是如何处理的?6、如何在 dot net core 中激活 session 功能?7、…...
案例-02.部门管理-查询
一.查询部门-需求 二.查询部门-思路 API接口文档 三.代码实现 1.controller层:负责与前端进行交互,接收前端所发来的请求 注:Slf4j用于记录日志使用,可以省略private static Logger log LoggerFactory.getLogger(DeptControlle…...
src和href区别
src和href区别 (1)请求资源类型不同(2)作用结果不同(3)解析方式不同 (1)请求资源类型不同 href 用来建立文档和元素之间的链接(是引用),常用的有a、linksrc 在请求src资源时候会将指向的资源下载并且应用到文档中(引入),常用的有script、iframe、image。 (2)作用结果不同 hr…...
Java每日精进·45天挑战·Day19
第一部分:移除数字以形成最小数的贪心算法实现 在编程的世界里,我们经常遇到需要对字符串表示的数字进行操作的问题。今天,我们要深入探讨一个具体的挑战:给定一个以字符串形式表示的非负整数 num 和一个整数 k,我们的…...
区块链的交易管理和共识机制
区块链的交易管理和共识机制是其核心功能,以下为你详细介绍它们的实现方式: 交易管理的实现 交易发起 • 用户使用钱包软件创建一笔交易,该交易包含发送方地址、接收方地址、转账金额等关键信息。同时,发送方会使用自己的私钥对…...
最新国内 ChatGPT Plus/Pro 获取教程
最后更新版本:20250202 教程介绍: 本文将详细介绍如何快速获取一张虚拟信用卡,并通过该卡来获取ChatGPT Plus和ChatGPT Pro。 # 教程全程约15分钟开通ChatGPT Plus会员帐号前准备工作 一个尚未升级的ChatGPT帐号!一张虚拟信用卡…...
Apollo 9.0 速度动态规划决策算法 – path time heuristic optimizer
文章目录 1. 动态规划2. 采样3. 代价函数3.1 障碍物代价3.2 距离终点代价3.3 速度代价3.4 加速度代价3.5 jerk代价 4. 回溯 这一章将来讲解速度决策算法,也就是SPEED_HEURISTIC_OPTIMIZER task里面的内容。Apollo 9.0使用动态规划算法进行速度决策,从类名…...
Apache Iceberg 与 Apache Hudi:数据湖领域的双雄对决
在数据存储和处理不断发展的领域中,数据湖仓的概念已经崭露头角,成为了一种变革性的力量。数据湖仓结合了数据仓库和数据湖的最佳元素,提供了一个统一的平台,支持数据科学、商业智能、人工智能/机器学习以及临时报告等多种关键功能…...
【LeetCode Hot100 普通数组】最大子数组和、合并区间、旋转数组、除自身以外数组的乘积、缺失的第一个正整数
普通数组 1. 最大子数组和(Maximum Subarray)解题思路动态规划的优化解法(Kadane 算法)核心思想 代码解析 2. 合并区间(Merge Intervals)解题思路代码实现 3. 旋转数组(Rotate Array)…...
共享存储-一步一步部署ceph分布式文件系统
一、Ceph 简介 Ceph 是一个开源的分布式文件系统。因为它还支持块存储、对象存储,所以很自 然的被用做云计算框架 openstack 或 cloudstack 整个存储后端。当然也可以单独作 为存储,例如部署一套集群作为对象存储、SAN 存储、NAS 存储等。 二、ceph 支…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...
label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...
12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...
安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...
【分享】推荐一些办公小工具
1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由:大部分的转换软件需要收费,要么功能不齐全,而开会员又用不了几次浪费钱,借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...
并发编程 - go版
1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...
4. TypeScript 类型推断与类型组合
一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式,自动确定它们的类型。 这一特性减少了显式类型注解的需要,在保持类型安全的同时简化了代码。通过分析上下文和初始值,TypeSc…...
