Spring Boot(Java21)实现Map/List<Map>到DTO的自定义映射与类型转换
通用Map/List
1. 依赖选择与引入
优先选用ModelMapper(轻量易配置,适合快速实现),也可选择MapStruct(编译期生成转换代码,性能更优)。以下是ModelMapper的依赖配置:
Maven
<dependency> <groupId>org.modelmapper</groupId> <artifactId>modelmapper</artifactId> <version>3.2.0</version> <!-- 最新稳定版 --> </dependency>
Gradle
implementation 'org.modelmapper:modelmapper:3.2.0'
2. 自定义映射规则配置
针对Map键名与DTO属性名不匹配的场景,通过ModelMapper的TypeMap预定义映射规则,统一配置在Spring配置类中:
import org.modelmapper.ModelMapper; import org.modelmapper.TypeMap; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class DtoMappingConfig { @Bean public ModelMapper modelMapper() { ModelMapper modelMapper = new ModelMapper(); // 示例:UserDTO的自定义映射(Map的"user_name"对应DTO的"username","age_str"转Integer类型的"age") TypeMap<Map<String, Object>, UserDTO> userDtoTypeMap = modelMapper.createTypeMap(Map.class, UserDTO.class); userDtoTypeMap.addMappings(mapper -> { mapper.map(src -> src.get("user_name"), UserDTO::setUsername); // 数值类型转换:String转Integer mapper.map(src -> Integer.parseInt(src.get("age_str").toString()), UserDTO::setAge); }); // 可添加更多DTO的映射规则 return modelMapper; } }
3. 实现通用转换Spring Bean
封装通用转换工具类,作为Spring Bean提供批量/单个转换方法,同时支持动态添加映射规则:
import org.modelmapper.ModelMapper; import org.modelmapper.TypeMap; import org.springframework.stereotype.Component; import java.util.List; import java.util.Map; import java.util.function.Consumer; import java.util.stream.Collectors; @Component public class GenericDtoConverter { private final ModelMapper modelMapper; public GenericDtoConverter(ModelMapper modelMapper) { this.modelMapper = modelMapper; } /** * 单个Map转DTO */ public <T> T convertMapToDto(Map<String, Object> map, Class<T> dtoClass) { return modelMapper.map(map, dtoClass); } /** * List<Map>转List<DTO> */ public <T> List<T> convertMapListToDtoList(List<Map<String, Object>> mapList, Class<T> dtoClass) { return mapList.stream() .map(map -> convertMapToDto(map, dtoClass)) .collect(Collectors.toList()); } /** * 动态添加自定义映射规则(适用于临时/运行时配置) */ public <T> void addCustomMapping(Class<T> dtoClass, Consumer<TypeMap<Map<String, Object>, T>> mappingConsumer) { TypeMap<Map<String, Object>, T> typeMap = modelMapper.createTypeMap(Map.class, dtoClass); mappingConsumer.accept(typeMap); } }
4. 数值类型转换增强配置
如需全局统一处理数值类型自动转换(如String转Number、Number类型互转),在DtoMappingConfig的modelMapper()方法中添加自定义转换器:
// 全局数值类型转换器 modelMapper.addConverter(context -> { Object source = context.getSource(); if (source == null) return null; Class<?> targetType = context.getDestinationType(); // String转Integer/Long/Double if (source instanceof String strValue) { if (targetType == Integer.class) return Integer.parseInt(strValue); if (targetType == Long.class) return Long.parseLong(strValue); if (targetType == Double.class) return Double.parseDouble(strValue); } // Number类型互转 if (source instanceof Number numValue) { if (targetType == Integer.class) return numValue.intValue(); if (targetType == Long.class) return numValue.longValue(); if (targetType == Double.class) return numValue.doubleValue(); } return source; });
5. 使用示例
定义DTO
public class UserDTO { private String username; private Integer age; private Double score; // Getter、Setter、toString方法省略 }
在业务类中调用转换器
import org.springframework.stereotype.Service; import java.util.List; import java.util.Map; @Service public class UserService { private final GenericDtoConverter dtoConverter; public UserService(GenericDtoConverter dtoConverter) { this.dtoConverter = dtoConverter; } public UserDTO processSingleUserMap(Map<String, Object> userMap) { return dtoConverter.convertMapToDto(userMap, UserDTO.class); } public List<UserDTO> processUserMapList(List<Map<String, Object>> userMapList) { return dtoConverter.convertMapListToDtoList(userMapList, UserDTO.class); } }
备选方案:MapStruct
若追求极致性能(无反射开销),可替换为MapStruct:
- 引入MapStruct核心依赖与注解处理器
- 定义通用转换接口并添加
@Mapper注解 - 通过
@Mapping配置字段映射与类型转换规则
内容的提问来源于stack exchange,提问作者Basharat Ali
相关产品推荐
相关产品推荐

