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

Jackson多态反序列化异常解决及正则匹配子类型实现问询

问题1 异常原因与修复方案

核心根因:你收到的JSON报文中data字段不是嵌套的JSON对象,而是被转义过的JSON字符串,Jackson默认不会自动对字符串类型的字段值做二次反序列化。

  • 你使用parser.getCodec().treeToValue(dataJson, type)时,dataJson本质是文本节点,Jackson尝试直接把字符串值转换为SeMessageData子类实例,自然会报错提示找不到对应类的字符串参数构造器
  • 你修改后的写法先取出data字段的字符串文本,再单独调用readValue做二次反序列化,完全匹配当前报文的结构,所以可以正常运行

如果想让最初的注解版代码正常运行,可以给SeMessage构造器的data参数加@JsonDeserialize注解,指定自定义反序列化器自动完成JSON字符串到对象的转换,也可以直接在ObjectMapper中注册全局的字符串转对象反序列化器适配该场景。

问题2 正则匹配子类型实现方案

Jackson原生的@JsonSubTypes.Type的name属性不支持正则匹配,但你可以通过自定义TypeIdResolver实现该需求,不需要写全量自定义反序列化器:

  1. 继承TypeNameIdResolver类,重写typeFromId方法,在方法内将所有子类型的name作为正则规则,和传入的action值匹配,返回匹配成功的子类型
  2. 在@JsonTypeInfo注解中指定using = 你自定义的Resolver类即可

示例实现参考:

public class RegexTypeIdResolver extends TypeNameIdResolver {
    protected RegexTypeIdResolver(MapperConfig<?> config, JavaType baseType, Collection<NamedType> subtypes, boolean forSer, boolean forDeser) {
        super(config, baseType, subtypes, forSer, forDeser);
    }

    @Override
    public JavaType typeFromId(DatabindContext context, String id) throws IOException {
        // 遍历所有注册的子类型,把name作为正则匹配传入的action值
        for (Map.Entry<String, JavaType> entry : _idTypes.entrySet()) {
            if (id.matches(entry.getKey())) {
                return entry.getValue();
            }
        }
        return super.typeFromId(context, id);
    }
}

修改SeMessage中data字段的注解即可生效:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "action", include = JsonTypeInfo.As.EXTERNAL_PROPERTY)
@JsonSubTypes({
    @JsonSubTypes.Type(value = Se155QuestionsActiveMessageData.class, name = "^155-questions-active$"),
    @JsonSubTypes.Type(value = SeQuestionsMessageData.class, name = "^(?!155)\\d+-questions-(?:active|newest(?:-tag-[a-z0-9]+)?)$")
})
@JsonTypeIdResolver(RegexTypeIdResolver.class)
final SeMessageData data

内容的提问来源于stack exchange,提问作者Oliver

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 09:15:04