MapStruct嵌套列表Source转扁平化Target带空值校验方案咨询
MapStruct嵌套列表空安全映射方案
下面提供3种支持空值校验、可自定义默认值的实现方案,都可以避免NPE问题:
方案1:Optional链式调用(无需额外自定义方法)
直接在expression中用JDK自带的Optional做全链路空安全校验,链式调用即可自动处理集合为null、集合为空、属性为null的场景,还能通过orElse设置自定义默认值:
@Mapper(imports = Optional.class) public interface MyMapper { @Mapping(target = "name", source = "name") @Mapping(target = "otherName", expression = "java(Optional.ofNullable(source.getOthers())" + ".filter(list -> !list.isEmpty())" + ".map(list -> list.get(0).getOtherName())" + ".orElse(\"\"))") // 可自定义默认值 @Mapping(target = "moreName", expression = "java(Optional.ofNullable(source.getOthers())" + ".filter(list -> !list.isEmpty())" + ".map(list -> list.get(0).getMores())" + ".filter(mores -> !mores.isEmpty())" + ".map(mores -> mores.get(0).getMoreName())" + ".orElse(\"\"))") Target map(Source source); }
优点:不用写额外的工具方法,代码简洁,全链路自动空校验。
方案2:自定义默认方法(推荐,可读性维护性最高)
在Mapper接口里封装自定义的空校验方法,通过@Named+qualifiedByName绑定映射关系,所有校验逻辑集中管理,可灵活调整规则:
import org.mapstruct.Named; @Mapper public interface MyMapper { // 自定义获取第一个Other的otherName的方法 @Named("getFirstOtherName") default String getFirstOtherName(Source source) { if (source.getOthers() == null || source.getOthers().isEmpty()) { return ""; // 自定义默认值 } Other firstOther = source.getOthers().get(0); return firstOther.getOtherName() != null ? firstOther.getOtherName() : ""; } // 自定义获取第一个More的moreName的方法 @Named("getFirstMoreName") default String getFirstMoreName(Source source) { if (source.getOthers() == null || source.getOthers().isEmpty()) { return ""; } Other firstOther = source.getOthers().get(0); if (firstOther.getMores() == null || firstOther.getMores().isEmpty()) { return ""; } More firstMore = firstOther.getMores().get(0); return firstMore.getMoreName() != null ? firstMore.getMoreName() : ""; } @Mapping(target = "name", source = "name") @Mapping(target = "otherName", source = "source", qualifiedByName = "getFirstOtherName") @Mapping(target = "moreName", source = "source", qualifiedByName = "getFirstMoreName") Target map(Source source); }
优点:逻辑清晰,调试方便,编译期即可检查语法错误,适合复杂校验场景。
方案3:借助第三方集合工具类
如果项目已经引入了Apache Commons、Guava等工具包,也可以直接在表达式中调用工具类做集合空判断:
// 以Apache Commons CollectionUtils为例 @Mapper(imports = {CollectionUtils.class}) public interface MyMapper { @Mapping(target = "otherName", expression = "java(CollectionUtils.isEmpty(source.getOthers()) ? \"\" : source.getOthers().get(0).getOtherName())") // moreName逻辑同理,多层判断即可 Target map(Source source); }
内容的提问来源于stack exchange,提问作者emoritz
相关产品推荐
相关产品推荐

