How can I map the following:
class Source {
String name;
List<Other> others;
}
class Other {
String otherName;
List<More> mores;
}
class More {
String moreName;
}
class Target {
String name;
String otherName;
String moreName;
}
Hoping it could be something like:
@Mapper
public interface MyMapper {
@Mapping(target = "name", source = "name")
@Mapping(target = "otherName", source = "others[0].otherName")
@Mapping(target = "morename", source = "others[0].mores[0].moreName")
Target map(Source source);
I see that 'expression = "java(others.get(0).otherName)"' can be used but there are no null checks when using expression, which could result in NullPointeException. Any suggestions with null checks and default can be applied?
CodePudding user response:
I think you need to see this example: MapStruct String to List mapping
Basically, you need to verify the size of the list before getting some elements.
CodePudding user response:
You can use expression
to check the null value and return something.
@Mapper
public interface MyMapper {
@Mapping(target = "name", source = "name")
@Mapping(target = "otherName", expression = "java(s.others != null && !s.others.isEmpty() ? s.others.get(0).otherName : \"\")")
@Mapping(target = "moreName", expression = "java(s.others != null && !s.others.isEmpty() && s.others.get(0).mores != null && !s.others.get(0).mores.isEmpty() ? s.others.get(0).mores.get(0).moreName : \"\")")
Target map(Source s);
}
// mapstruct code generate.
public class MyMapperImpl implements MyMapper {
@Override
public Target map(Source s) {
if ( s == null ) {
return null;
}
Target target = new Target();
target.name = s.name;
target.otherName = s.others != null && !s.others.isEmpty() ? s.others.get(0).otherName : "";
target.moreName = s.others != null && !s.others.isEmpty() && s.others.get(0).mores != null && !s.others.get(0).mores.isEmpty() ? s.others.get(0).mores.get(0).moreName : "";
return target;
}
}
If you want readable and reduce the check null duplicate code, you can use the interface default
method and use org.springframework.util.ObjectUtils.isEmpty()
.
@Mapper
public interface MyMapper {
@Mapping(target = "name", source = "name")
@Mapping(target = "otherName", expression = "java(getFirstOtherName(s))")
@Mapping(target = "moreName", expression = "java(getFirstMoreName(s))")
Target map(Source s);
default String getFirstOtherName(Source s) {
return !ObjectUtils.isEmpty(s.others) ? s.others.get(0).otherName : "";
}
default String getFirstMoreName(Source s) {
return !ObjectUtils.isEmpty(s.others) && !ObjectUtils.isEmpty(s.others.get(0).mores) ? s.others.get(0).mores.get(0).moreName : "";
}
}
// mapstruct code generate.
public class MyMapperImpl implements MyMapper {
@Override
public Target map(Source s) {
if ( s == null ) {
return null;
}
Target target = new Target();
target.name = s.name;
target.otherName = getFirstOtherName(s);
target.moreName = getFirstMoreName(s);
return target;
}
}