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

使用ModelMapper转换泛型Wrapper<City>到Wrapper<CityDto>失败排查

ModelMapper转换泛型Wrapper到Wrapper时嵌套列表未正确转换的原因

问题根源

ModelMapper处理泛型容器类时,默认只做浅层次的字段匹配,不会自动递归处理泛型参数的深层转换:

  • 当你用TypeToken<Wrapper<CityDto>>指定目标类型时,ModelMapper能正确创建Wrapper<CityDto>实例,并直接拷贝count字段(因为类型都是Integer,完全匹配)。
  • 但对于entities字段,源是List<City>、目标是List<CityDto>,由于Java泛型的类型擦除特性,运行时ModelMapper无法自动识别出需要把列表里的每个City转成CityDto,而是直接把源列表的元素原样赋值给目标Wrapper的entities字段,导致列表元素还是City类型,强转成CityDto时触发ClassCastException。

临时方案有效的原因

你的手动转换逻辑是先单独处理列表转换,再封装到Wrapper中:

  • 当你用new TypeToken<List<CityDto>>() {}.getType()明确指定列表的目标类型时,ModelMapper能清楚知道需要遍历列表,把每个City转换成CityDto,因此能正确完成元素转换。

可选优化方案(无需手动封装)

如果不想每次都拆分转换步骤,可以给ModelMapper注册自定义转换器,显式处理Wrapper的泛型转换逻辑:

ModelMapper modelMapper = new ModelMapper();
modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.LOOSE);

// 注册针对Wrapper<City>到Wrapper<CityDto>的转换器
modelMapper.addConverter(new Converter<Wrapper<City>, Wrapper<CityDto>>() {
    @Override
    public Wrapper<CityDto> convert(MappingContext<Wrapper<City>, Wrapper<CityDto>> context) {
        Wrapper<City> source = context.getSource();
        Wrapper<CityDto> target = new Wrapper<>();
        target.setCount(source.getCount());
        // 单独转换列表元素
        List<CityDto> dtoList = modelMapper.map(source.getEntities(), new TypeToken<List<CityDto>>() {}.getType());
        target.setEntities(dtoList);
        return target;
    }
});

// 之后直接调用map即可完成完整转换
Wrapper<City> sourceWrapper = ...;
Wrapper<CityDto> result = modelMapper.map(sourceWrapper, Wrapper.class);

如果需要支持多种类型的Wrapper转换,可以写一个通用的转换器工具方法:

// 通用Wrapper转换器生成方法
public static <S, D> Converter<Wrapper<S>, Wrapper<D>> createWrapperConverter(ModelMapper mapper, Class<D> destClass) {
    return context -> {
        Wrapper<S> source = context.getSource();
        Wrapper<D> target = new Wrapper<>();
        target.setCount(source.getCount());
        List<D> dtoList = mapper.map(source.getEntities(), new TypeToken<List<D>>() {}.getType());
        target.setEntities(dtoList);
        return target;
    };
}

// 使用示例
modelMapper.addConverter(createWrapperConverter(modelMapper, CityDto.class));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 18:01:25