如何基于标志位让MapStruct选择不同源字段映射至单个目标字段
MapStruct 根据条件二选一映射属性的解决方案
问题背景
现有类定义及映射器代码如下:
// Source 和 Target 类定义 public class Source { public A a; public B b; public boolean flag; } public class Target { public AorB a_or_b; } // 映射器接口 interface Mapper { @Mapping(target = "a_or_b", source = "source.a", conditionExpression = "java(source.flag == true)") // MapStruct 报错:Target property "a_or_b" must not be mapped more than once. @Mapping(target = "a_or_b", source = "source.b", conditionExpression = "java(source.flag == false)") Target map(Source source); AorB map(A a); // 预期 flag 为 true 时被调用 AorB map(B b); // 预期 flag 为 false 时被调用 }
需求是根据Source.flag的值,将Source.a或Source.b二选一映射到Target.a_or_b,但当前因重复映射同一目标属性触发MapStruct报错,需解决该问题。
可行方案
该需求完全可以实现,以下是两种简洁的解决方式:
方式一:使用expression属性编写条件逻辑
移除重复的@Mapping注解,通过单个@Mapping的expression直接嵌入三目运算符逻辑,让MapStruct根据flag选择对应转换方法:
interface Mapper { @Mapping(target = "a_or_b", expression = "java(source.flag ? map(source.a) : map(source.b))") Target map(Source source); AorB map(A a); AorB map(B b); }
- 此方式仅对
a_or_b做一次映射声明,规避重复映射报错; - MapStruct会自动生成对应代码,根据
flag的布尔值调用正确的转换方法。
方式二:自定义默认方法控制映射流程
通过在映射器接口中定义默认方法,手动控制整个映射逻辑,适合需要更复杂处理的场景:
interface Mapper { default Target map(Source source) { Target target = new Target(); target.a_or_b = source.flag ? map(source.a) : map(source.b); // 若有其他属性需自动映射,可在此处调用MapStruct生成的辅助映射方法 // mapRemainingProperties(source, target); return target; } AorB map(A a); AorB map(B b); // 可选:声明其他属性的自动映射方法,MapStruct会自动实现 // void mapRemainingProperties(Source source, @MappingTarget Target target); }
内容的提问来源于stack exchange,提问作者Zartc
相关产品推荐
相关产品推荐

