You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何配置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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 00:42:21