如何配置msgspec实现API响应动态解析为正确类型?
问题描述
现有一段无法正常运行的Python代码,JSON输入格式固定,mediaType字段存在两种嵌套结构:一种是包含Image键的对象,另一种是包含Video键的对象。需要配置msgspec,让它自动选择对应的Image/Video结构体完成解析,最终得到对应类型的实例。
原代码如下:
import json import msgspec from typing import Union class Image(msgspec.Struct): format: str class Video(msgspec.Struct): format: str MediaType = Union[Image, Video] class Media(msgspec.Struct): width: int height: int mediaType: MediaType DECODER = msgspec.json.Decoder(Media) image = {"width": 100, "height": 200, "mediaType": { "Image": { "format": "jpg" } } } video = {"width": 100, "height": 200, "mediaType": { "Video": { "format": "mp4" } } } image_str = json.dumps(image) video_str = json.dumps(video) image_str_decoded = DECODER.decode(image_str) video_str_decoded = DECODER.decode(video_str) print(image_str_decoded) print(video_str_decoded)
期望解析结果:
image_str_decoded(width=100, height=200, mediaType=Image(format=jpg)) video_str_decoded(width=100, height=200, mediaType=Video(format=mp4))
解决方案
msgspec默认的Union类型解析无法识别这种外层带类型键的嵌套结构,需要通过自定义解码钩子处理MediaType的解析逻辑,具体实现如下:
修改后的代码:
import json import msgspec from typing import Union, Any class Image(msgspec.Struct): format: str class Video(msgspec.Struct): format: str MediaType = Union[Image, Video] class Media(msgspec.Struct): width: int height: int mediaType: MediaType def media_type_hook(obj: Any, type: type) -> MediaType: # 解析mediaType的嵌套结构,匹配对应类型并实例化 if isinstance(obj, dict): if "Image" in obj: return msgspec.convert(obj["Image"], Image) elif "Video" in obj: return msgspec.convert(obj["Video"], Video) raise ValueError(f"无法识别的媒体类型: {obj}") # 注册钩子,指定处理MediaType类型 DECODER = msgspec.json.Decoder(Media, hooks={MediaType: media_type_hook}) image = {"width": 100, "height": 200, "mediaType": { "Image": { "format": "jpg" } } } video = {"width": 100, "height": 200, "mediaType": { "Video": { "format": "mp4" } } } image_str = json.dumps(image) video_str = json.dumps(video) image_str_decoded = DECODER.decode(image_str) video_str_decoded = DECODER.decode(video_str) print(image_str_decoded) print(video_str_decoded)
代码说明
media_type_hook函数:接收解析后的mediaType字典,检查其中的标识键(Image/Video),用msgspec.convert将内层数据转换为对应结构体实例。- 解码器通过
hooks={MediaType: media_type_hook}注册钩子,当解析MediaType类型字段时,自动触发钩子处理数据。
运行后输出结果:
Media(width=100, height=200, mediaType=Image(format='jpg')) Media(width=100, height=200, mediaType=Video(format='mp4'))
内容的提问来源于stack exchange,提问作者miran80
相关产品推荐
相关产品推荐

