MapStruct:在映射之前过滤列表

2024-02-19

我在其他地方看到过这个问题,但并不完全相同,并且没有适合我们用例的答案。

假设我在源对象中有一个列表字段:

List<MySourceElement> mySourceList;

和相应的目标字段:

List<MyTargetElement> myTargetList;

我只是希望能够在执行 mySourceList 的标准映射器以映射到 myTargetList 之前,通过 MySourceElement 的某些属性来过滤源 mySourceList 中的元素。

假设 MySourceElement 有一个布尔属性 isValid 并且我们的过滤谓词只是 (isValid == true),而 MyTargetElement 没有相应的布尔值。

我尝试了多种方法,包括@DecolatedWith和qualifiedBy:

  1. 对于如此简单的用例,@DecolatedWith 与 Guice 注入变得过于复杂/令人费解,并且此功能也在 MapStruct 文档中列为 jsr330 的实验性功能。

  2. QualifiedBy 不起作用(即,我无法让 Mapstruct 在实现中应用 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 来实现此目的,而不是让 QualifiedBy 工作,但我不清楚如何从文档中做到这一点,特别是因为对于所有意图和目的,源对象应该被认为是不可变的。

任何有关以这种方式结合调用映射器进行集合过滤的最简单、首选方法的指导将不胜感激。


有一个请求的功能映射结构/映射结构#1610 https://github.com/mapstruct/mapstruct/issues/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);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MapStruct:在映射之前过滤列表 的相关文章

随机推荐