Java MapStruct:嵌套的Iterable到Non-Iterable映射?

Java MapStruct:嵌套的Iterable到Non-Iterable映射?,java,mapstruct,Java,Mapstruct,我发现了这个关于使用限定符从Iterable到Non-Iterable映射的示例: 但是如何使此映射能够映射嵌套属性(使用点注释) 例如,将源对象中集合的第一个元素的字段xyz映射到目标对象上的普通字段 该示例定义了一个限定符 @Qualifier @Target(ElementType.METHOD) @Retention(RetentionPolicy.SOURCE) public @interface FirstElement { } 然后定义一个自定义映射器 public

我发现了这个关于使用限定符从Iterable到Non-Iterable映射的示例:

但是如何使此映射能够映射嵌套属性(使用点注释)

例如,将源对象中集合的第一个元素的字段xyz映射到目标对象上的普通字段

该示例定义了一个限定符

@Qualifier  
@Target(ElementType.METHOD)  
@Retention(RetentionPolicy.SOURCE)  
public @interface FirstElement {
}
然后定义一个自定义映射器

public class MapperUtils {
    @FirstElement
    public <T> T first(List<T> in) {
        if (in != null && !in.isEmpty()) {
            return in.get(0);
        }
        else {
            return null;
        }
    }
}
但是,如果我想从电子邮件集合的第一个元素中提取一个特定字段,例如,像我对code
emails所做的那样。get(0)。getEmailAddress

例如,我希望编写如下映射:

@Mapping(target = "emailaddress", source = "emails[0].emailAddress")

您只需更改
MapperUtils

public class MapperUtils {
    @FirstElement
    public String firstEmailAddress(List<Person> in) {
        if (in != null && !in.isEmpty()) {
            return in.get(0).getEmailAddress();
        }
        else {
            return null;
       }
    }
}

但是,如果您犯了错误,使用表达式可能会导致编译时问题。MapStruct不检查表达式的有效性,而是按原样使用它。

另一个选项是在映射器中使用下面的行 这将使用helperclass来帮助转换

@Mapping(target = "emailaddress", qualifiedByName={"helperClass", "emailsToAddress"}, 
source = "emails")
在@Mapper的组件使用部分添加helperclass

@Mapper(        
        componentModel="spring",
        uses ={                 
                helperClass.class
       },               
       ) 
helper类看起来像

@Component
@Named("helperClass")
public class helperClass {      

@Named("emailsToAddress")
    public String emailsToAddress(List<Email> emails) {
        if(emails != null || !emails.isEmpty )
            return emails.get(0).getAddress();
        else
            return null;
    }   
@组件
@命名(“帮助类”)
公共类帮助类{
@命名(“电子邮件地址”)
公共字符串emailsToAddress(列出电子邮件){
if(emails!=null | |!emails.isEmpty)
返回电子邮件。get(0)。getAddress();
其他的
返回null;
}   

是的,我知道,但使用此解决方案,我必须为Iterable中包含的每个特定类型实现一个方法。我希望获得第一个元素,然后使用点符号访问此类型的字段。因此,我希望编写如下内容:@Mapping(target=“emailaddress”,source=“emails.emailaddress”,qualifiedBy=FirstElement.class),但也可以使用@Mapping(target=“prefix”,source=“phoneNumbers.prefix”,qualifiedBy=FirstElement.class),而无需为每个属性映射编写方法。例如,我想编写一个这样的映射程序:@Mapping(target=“emailaddress”,source=“emails[0].emailaddress”)你是对的。还有一种方法可以做到这一点。你可以使用
@Maping
expression
属性。例如
@Mapping(target=“emailaddress”,expression=“emails!=null&&!emails.isEmpty()?emails.get(0).getEmailAddress():null”}
。如果电子邮件是映射方法的一部分,则可以使用
电子邮件,如果
电子邮件
是源参数的属性,则必须执行
source.getEmails()
@Mapper(        
        componentModel="spring",
        uses ={                 
                helperClass.class
       },               
       ) 
@Component
@Named("helperClass")
public class helperClass {      

@Named("emailsToAddress")
    public String emailsToAddress(List<Email> emails) {
        if(emails != null || !emails.isEmpty )
            return emails.get(0).getAddress();
        else
            return null;
    }