使用Spring Mapper映射Map类型对象时遇映射错误,求解决方案
看起来你在使用MapStruct的@Mapper注解时遇到了类型映射不匹配的问题,我来帮你梳理下问题根源和解决办法:
问题根源分析
首先先纠正一个代码里的语法错误:你的HostsCounters类中泛型的写法有误,引号不应该出现在泛型参数里,正确的泛型声明应该是Map<String, Map<String, Long>>,而不是Map<"String",Map<"String","Long">>,这个语法错误会先导致编译失败,得先修正。
回到映射错误本身:错误提示说无法将Map类型映射到HostsCounters类型,这是因为MapStruct默认不知道如何把一个Map对象转换成你的自定义HostsCounters类实例——MapStruct只能自动映射属性结构匹配的对象,对于这种"包装类+内部集合/Map"的结构,需要你手动声明映射规则。
另外注意下你的ResponseMapper接口中toResponse方法的参数名:HostsCounters hostsList,这个参数名和HostsCounters类里的属性名重名了,虽然不影响编译,但容易混淆,建议改成更清晰的名字比如HostsCounters hostsCounters。
解决方案
方案1:添加自定义映射方法
在你的ResponseMapper接口中声明一个专门的方法,告诉MapStruct如何把Map<String, Map<String, Long>>转换成HostsCounters:
@Mapper(componentModel = "spring") public interface ResponseMapper { // 自定义Map到HostsCounters的映射方法 default HostsCounters mapToHostsCounters(Map<String, Map<String, Long>> hostsMap) { HostsCounters hostsCounters = new HostsCounters(); hostsCounters.setHostsList(hostsMap); return hostsCounters; } // 原有的转换方法(注意修改参数名避免混淆) GeneralResponse toResponse(SevCount sevCount, HostsCounters hostsCounters, List<RegDAO> reg); }
方案2:检查调用toResponse时的参数类型
如果你在调用toResponse的时候,不小心传入了一个Map对象而不是HostsCounters对象,那只需要修正调用代码,先把Map包装成HostsCounters实例再传入:
// 假设你有一个Map<String, Map<String, Long>>类型的变量hostsMap HostsCounters hostsCounters = new HostsCounters(hostsMap); GeneralResponse response = responseMapper.toResponse(sevCount, hostsCounters, regList);
修正后的完整代码示例
修正后的HostsCounters类
@Data @NoArgsConstructor @AllArgsConstructor public class HostsCounters { // 去掉泛型参数里的引号,修正语法错误 private Map<String, Map<String, Long>> hostsList; }
修正后的ResponseMapper接口
@Mapper(componentModel = "spring") public interface ResponseMapper { default HostsCounters mapToHostsCounters(Map<String, Map<String, Long>> hostsMap) { return new HostsCounters(hostsMap); } GeneralResponse toResponse(SevCount sevCount, HostsCounters hostsCounters, List<RegDAO> reg); }
这样修改后,MapStruct就能正确处理类型映射了,编译错误应该就能解决。
内容的提问来源于stack exchange,提问作者אברגיל יעקובו

