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

Jackson泛型方法数据解析异常:java.util.LinkedHashMap无法转换为自定义类问题求助

问题原因:Java泛型类型擦除导致Jackson无法识别目标类型

你遇到的ClassCastException核心原因是Java的泛型类型擦除机制。当你在doNestedListGet方法中使用new TypeReference<PageWrapper<List<T>>>()时,编译后泛型参数T的实际类型会被擦除,Jackson在运行时无法知道T具体是WBEmployee,只能默认将JSON数组反序列化为LinkedHashMap的列表,这就导致后续你尝试把这些LinkedHashMap强转为WBEmployee时抛出异常。

而本地测试能正常运行,是因为你直接创建了具体的TypeReference<PageWrapper<List<WBEmployee>>>()——匿名内部类会保留泛型类型的元数据,Jackson可以正确识别出要反序列化为WBEmployee列表。


两种可行的解决方案

方案1:让调用方传入具体的TypeReference

修改doNestedListGet方法,让调用方明确传入包含具体泛型类型的TypeReference,这样Jackson就能获取到准确的类型信息:

@Override
public <T> PageWrapper<List<T>> doNestedListGet(TypeReference<PageWrapper<List<T>>> typeRef, HttpUrl url) throws IOException {
    var req = this.reqBuilder.url(url).build();
    try (var res = this.webClient.newCall(req).execute()) {
        if (!res.isSuccessful()) {
            throw new IOException(String.format("API call failed: %s", res));
        }
        var jString = res.body().string();
        return this.mapper.readValue(jString, typeRef);
    }
}

然后在getList方法中调用时传入具体的TypeReference:

public List<WBEmployee> getList(int page, WBEmploymentStatus employmentStatus) throws IOException {
    var url = this.baseEndpoint.newBuilder()
            .addQueryParameter("page", String.valueOf(page))
            .addQueryParameter("status", employmentStatus.getDescr()).build();
    return this.wbClient.doNestedListGet(
        new TypeReference<PageWrapper<List<WBEmployee>>>() {}, 
        url
    ).getPgData();
}

方案2:利用Jackson的TypeFactory构造具体类型

如果你不想修改调用方的代码,可以在doNestedListGet内部,通过传入的Class<T>结合Jackson的TypeFactory来构造准确的JavaType,避免类型擦除的影响:

@Override
public <T> PageWrapper<List<T>> doNestedListGet(Class<T> type, HttpUrl url) throws IOException {
    var req = this.reqBuilder.url(url).build();
    try (var res = this.webClient.newCall(req).execute()) {
        if (!res.isSuccessful()) {
            throw new IOException(String.format("API call failed: %s", res));
        }
        var jString = res.body().string();
        // 先构造List<T>的类型
        JavaType listType = mapper.getTypeFactory().constructCollectionType(List.class, type);
        // 再构造PageWrapper<List<T>>的类型
        JavaType wrapperType = mapper.getTypeFactory().constructParametricType(PageWrapper.class, listType);
        return this.mapper.readValue(jString, wrapperType);
    }
}

这种方式下,原来的getList方法不需要任何修改,因为我们内部已经通过Class<T>构建了正确的泛型类型。


补充说明

你的PageWrapper类中的@JsonAlias注解是正确的配置,它能处理不同API返回的不同key(比如documents/employees/some_key),这个不是导致问题的原因,无需修改。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 19:17:31