MapStruct:嵌套的可迭代到不可迭代的映射?
MapStruct : Nested Iterable to Non-Iterable mapping?
我找到了这个关于使用限定符将 Iterable 映射到 Non-Iterable 的示例:
https://github.com/mapstruct/mapstruct-examples/tree/master/mapstruct-iterable-to-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;
}
}
}
最后,映射定义为
@Mapping(target = "emailaddress", source = "emails", qualifiedBy = FirstElement.class )
但是如果我想从电子邮件集合的第一个元素中提取一个特定的字段,例如就像我会用代码 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;
}
}
}
基本上Annotated方法的参数应该有你想映射的Iterable
,return类型应该是你想映射到的Non-Iterable
。
如果您不想为映射创建自定义映射,另一种方法是使用 expression
属性。
例如:
@Mapping(target = "emailaddress", expression = "emails != null && !emails.isEmpty() ? emails.get(0).getEmailAddress() : null")
但是,使用表达式时要小心,如果出错可能会导致编译时问题。 MapStruct 不检查表达式的有效性并按原样使用它。
另一种选择是在您的映射器中使用以下行
这使用助手class 来帮助转换
@Mapping(target = "emailaddress", qualifiedByName={"helperClass", "emailsToAddress"},
source = "emails")
在@Mapper使用的组件中添加helperclass
@Mapper(
componentModel="spring",
uses ={
helperClass.class
},
)
助手 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;
}
我找到了这个关于使用限定符将 Iterable 映射到 Non-Iterable 的示例:
https://github.com/mapstruct/mapstruct-examples/tree/master/mapstruct-iterable-to-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;
}
}
}
最后,映射定义为
@Mapping(target = "emailaddress", source = "emails", qualifiedBy = FirstElement.class )
但是如果我想从电子邮件集合的第一个元素中提取一个特定的字段,例如就像我会用代码 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;
}
}
}
基本上Annotated方法的参数应该有你想映射的Iterable
,return类型应该是你想映射到的Non-Iterable
。
如果您不想为映射创建自定义映射,另一种方法是使用 expression
属性。
例如:
@Mapping(target = "emailaddress", expression = "emails != null && !emails.isEmpty() ? emails.get(0).getEmailAddress() : null")
但是,使用表达式时要小心,如果出错可能会导致编译时问题。 MapStruct 不检查表达式的有效性并按原样使用它。
另一种选择是在您的映射器中使用以下行 这使用助手class 来帮助转换
@Mapping(target = "emailaddress", qualifiedByName={"helperClass", "emailsToAddress"},
source = "emails")
在@Mapper使用的组件中添加helperclass
@Mapper(
componentModel="spring",
uses ={
helperClass.class
},
)
助手 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;
}