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

如何用MapStruct将含3个Map的Response映射为ResponseDTO?

问题

能否使用MapStruct将内部包含3个Map的Response对象映射为同样包含3个Map的ResponseDTO对象?相关代码如下:

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class ResponseDTO implements Serializable {

    private Map<String, Map<String, ResponseItemDTO>> map1;
    private Map<String, Map<String, ResponseItemDTO>> map2;
    private Map<String, Map<String, ResponseItemDTO>> map3;

}

public class ResponseItemDTO implements Serializable {

    private String id;
    private String label;
    private String type;

    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "value")
    @JsonSubTypes({
        @JsonSubTypes.Type(value = SimpleString.class, name = "simpleString"),
        @JsonSubTypes.Type(value = OverrideString.class, name = "overrideString")
    })
    public interface Value {}
}

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@JsonTypeName("simpleString")
public class SimpleString implements ResponseItemDTO.Value {
    
    @JsonProperty("value")
    private String value;

}

@Mapper
interface ResponseMapper {
    ResponseMapper INSTANCE = Mappers.getMapper(ResponseMapper.class);

    @Mapping(target = "map1", source = "response.map1")
    @Mapping(target = "map2", source = "response.map2")
    @Mapping(target = "map3", source = "response.map3")
    ResponseDTO mapResponseDTO(Response response);
    
     // 报错提示需要添加这些映射方法
    Map<String, Map<String, ResponseItemDTO>> map1(Map<String, ResponseItem> map1);
    Map<String,ResponseItemDTO> map(ResponseItem value);
}

遇到的错误信息:

java: The return type Map<String,ResponseItemDTO> is an abstract class or interface. Provide a non abstract / non interface result type or a factory method.

尝试添加了默认方法但无效:

default SimpleString createSimpleString() {
       return new SimpleString();
}
解决方案

问题核心是MapStruct无法自动推断ResponseItem到ResponseItemDTO具体实现类的映射逻辑,且原映射方法返回接口类型,导致框架无法确定实例化的具体类。以下是修复步骤:

  1. 编写具体类型的映射方法
    为每个ResponseItem对应的DTO实现类编写映射方法,比如:

    SimpleString mapToSimpleString(ResponseItem source);
    OverrideString mapToOverrideString(ResponseItem source);
    

    MapStruct会自动根据字段名匹配映射,若字段名不一致可添加@Mapping注解调整。

  2. 自定义嵌套Map的映射逻辑
    替换原有的Map<String,ResponseItemDTO> map(ResponseItem value);方法,改为处理整个Map的自定义逻辑,根据源对象的标识选择具体的映射实现:

    default Map<String, ResponseItemDTO.Value> mapItemMap(Map<String, ResponseItem> sourceMap) {
        if (sourceMap == null) return null;
        Map<String, ResponseItemDTO.Value> targetMap = new HashMap<>();
        for (Map.Entry<String, ResponseItem> entry : sourceMap.entrySet()) {
            ResponseItem item = entry.getValue();
            ResponseItemDTO.Value dto;
            // 根据item的type字段判断要映射到哪个具体DTO类
            if ("simpleString".equals(item.getType())) {
                dto = mapToSimpleString(item);
            } else if ("overrideString".equals(item.getType())) {
                dto = mapToOverrideString(item);
            } else {
                throw new IllegalArgumentException("未知的ResponseItem类型:" + item.getType());
            }
            targetMap.put(entry.getKey(), dto);
        }
        return targetMap;
    }
    
  3. 实现顶层Map的映射
    编写处理外层Map的默认方法,调用上面的嵌套Map映射逻辑:

    default Map<String, Map<String, ResponseItemDTO.Value>> mapTopLevelMap(Map<String, Map<String, ResponseItem>> source) {
        if (source == null) return null;
        Map<String, Map<String, ResponseItemDTO.Value>> target = new HashMap<>();
        for (Map.Entry<String, Map<String, ResponseItem>> entry : source.entrySet()) {
            target.put(entry.getKey(), mapItemMap(entry.getValue()));
        }
        return target;
    }
    
  4. 简化主映射方法
    移除主方法中多余的@Mapping注解,MapStruct会自动匹配上面的自定义映射方法:

    ResponseDTO mapResponseDTO(Response response);
    
  5. 移除无效的默认方法
    之前添加的createSimpleString方法对当前场景无用,直接删除即可。

注意:原代码中SimpleString实现的是ResponseItemDTO类而非ResponseItemDTO.Value接口,这会导致类型不匹配,需要修正为implements ResponseItemDTO.Value。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 20:47:09