使用带有 MapStruct 的构建器将空值映射到默认值
Map null values to default using builder with MapStruct
我想将字段从 Source
映射到 Target
class,如果源值为 null
,我想将其转换为基于默认值关于数据类型(“”表示字符串,0 表示数字类型等)。为了设置值,我没有使用常规的设置器,而是使用构建器(使用 protobuf,因此方法的名称是 newBuilder()
和 build()
)。
class Source {
private final String value; // getter
}
class Target {
private final String value;
public static Builder newBuilder() {return new Builder()}
public static class Builder {
public static setValue() {/*Set the field*/}
public static Target build() {/*Return the constructed instance*/}
}
我的映射器看起来像这样:
@Mapper(
nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.SET_TO_DEFAULT,
nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT
)
public interface TargetMapper {
Target map(Source source);
}
使用此代码生成的映射器实现调用 target.setValue(source.getValue())
,而不是执行 null 检查并设置默认值 if source returns null
。有趣的是,当我将以下注释添加到 map
方法时,实现中存在空检查。
@Mapping(source="value", target="value", nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.SET_TO_DEFAULT)
这是带有构建器的 MapStruct 中的一个错误,还是我缺少一些能够将 null 映射设置为默认策略的配置,而不是在所有字段映射上复制它?
编辑:出于某种原因,将 nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS
添加到 class 级别 @Mapper
注释会添加空检查,但不会显式设置值,只是跳过对 setValue
。对于 protobuf,这没问题,因为这个功能在库中,但对于其他实现,该字段将保持为空。
@Mapping(source="value", target="value", nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.SET_TO_DEFAULT)
适用于更新方法(因此具有 @MappingTarget
注释参数的方法
常规方法没有真正的对应物:
1. NullValueMappingStragegy
适用于 bean 参数本身。
2. NullValueCheckStragegy
会检查 bean 属性,但不会 return 默认值。
命名其实并不高明,而且历史悠久。这一天我们还是有意向的。
一种解决方案是使用对象工厂创建构建器目标对象并使用默认值预填充它,然后让 MapStuct 有一天覆盖这些。
也许你可以这样做:
@Mapper(
// to perform a null check
nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS
)
public interface TargetMapper {
Target map(Source source);
}
// to create a pre-defined object (defaults set a-priori). Not sure
// whether this works with builders.. just try
@ObjectFactory
default Target.Builder create() {
Target.Builder builder = Target.newBuilder();
builder.setValueX( "someDefaultValue" );
return builder;
}
我想将字段从 Source
映射到 Target
class,如果源值为 null
,我想将其转换为基于默认值关于数据类型(“”表示字符串,0 表示数字类型等)。为了设置值,我没有使用常规的设置器,而是使用构建器(使用 protobuf,因此方法的名称是 newBuilder()
和 build()
)。
class Source {
private final String value; // getter
}
class Target {
private final String value;
public static Builder newBuilder() {return new Builder()}
public static class Builder {
public static setValue() {/*Set the field*/}
public static Target build() {/*Return the constructed instance*/}
}
我的映射器看起来像这样:
@Mapper(
nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.SET_TO_DEFAULT,
nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT
)
public interface TargetMapper {
Target map(Source source);
}
使用此代码生成的映射器实现调用 target.setValue(source.getValue())
,而不是执行 null 检查并设置默认值 if source returns null
。有趣的是,当我将以下注释添加到 map
方法时,实现中存在空检查。
@Mapping(source="value", target="value", nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.SET_TO_DEFAULT)
这是带有构建器的 MapStruct 中的一个错误,还是我缺少一些能够将 null 映射设置为默认策略的配置,而不是在所有字段映射上复制它?
编辑:出于某种原因,将 nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS
添加到 class 级别 @Mapper
注释会添加空检查,但不会显式设置值,只是跳过对 setValue
。对于 protobuf,这没问题,因为这个功能在库中,但对于其他实现,该字段将保持为空。
@Mapping(source="value", target="value", nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.SET_TO_DEFAULT)
适用于更新方法(因此具有 @MappingTarget
注释参数的方法
常规方法没有真正的对应物:
1. NullValueMappingStragegy
适用于 bean 参数本身。
2. NullValueCheckStragegy
会检查 bean 属性,但不会 return 默认值。
命名其实并不高明,而且历史悠久。这一天我们还是有意向的。
一种解决方案是使用对象工厂创建构建器目标对象并使用默认值预填充它,然后让 MapStuct 有一天覆盖这些。
也许你可以这样做:
@Mapper(
// to perform a null check
nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS
)
public interface TargetMapper {
Target map(Source source);
}
// to create a pre-defined object (defaults set a-priori). Not sure
// whether this works with builders.. just try
@ObjectFactory
default Target.Builder create() {
Target.Builder builder = Target.newBuilder();
builder.setValueX( "someDefaultValue" );
return builder;
}