我已经在其他地方看到过这个问题但在相同的背景下并没有得到适用于我们用例的答案。
假设我在源对象中有一个列表字段:
List<MySourceElement> mySourceList;
和相应的目标字段:
List<MyTargetElement> myTargetList;
我只是希望能够在执行mySourceList的标准映射器以映射到myTargetList之前,通过MySourceElement的某些属性过滤源mySourceList中的元素。
假设MySourceElement有一个布尔属性isValid,我们的过滤谓词就是(isValid == true),而MyTargetElement没有相应的布尔值。
我尝试了很多方法,包括@DecoratedWith和qualifiedBy:
qualifiedBy方法类似于:
@FilterForValid
public List<MySourceElement> filterForValid(List<MySourceElement> mySourceElement) {
... implementation ...
}
我的映射器声明如下:
@Mapping(source = "mySourceList", target = "myTargetList", qualifiedBy = FilterForValid.class)
Target sourceToTarget(Source source);
我想要一个qualifiedBy的实现,如:
target.withMyTargetList(
mySourceListToMyTargetList(filterUtil.filterForValid(source.getMySourceList)));
为了获得合格的工作,我很乐意找出如何使用@BeforeMapping,但我不清楚如何从文档中做到这一点,特别是因为对于所有意图和目的,源对象应该被认为是不可改变的。
关于以最简单,优选的方式进行集合过滤以及以这种方式调用映射器的任何指导将是值得赞赏的。
有一个请求的功能mapstruct/mapstruct#1610,允许在这里使用开箱即用支持这样的东西。说到这一点,解决这个问题的方法是使用@Context
注释。您的映射器可以如下所示:
@Mapper
public interface MyMapper {
Target map(Source source, @Context Predicate<MySourceElement> predicate);
default List<MySourceElement> mapAndFilter(List<MySourceElement> list, @Context Predicate<MySourceElement> predicate) {
List<MySourceElement> newList = new ArrayList<>();
for(MySourceElement el : list) {
if (predicate.test(el)) {
newList.add(map(el));
}
}
return newList;
}
MySourceElement map(MySourceElement el);
}