MapStruct:根据(布尔)值排除 属性

MapStruct: exclude property based on (boolean) value

我知道 MapStruct 可以忽略未映射的属性和特定的目标属性,但是是否可以根据其实际值排除 属性?

我有布尔字段,只有当它们为假时我才想排除它们。

提前致谢!

示例:

实体:

@Entity
@Table(name = "vehicle")
@Getter @Setter
public class Vehicle {
   @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
   private int id;
   private String name;
   private boolean hasWheels;
   private boolean hasWings;
   private boolean hasBrakes;
}

DTO:

@Getter @Setter
public class VehicleDTO {

   private String name;
   private boolean hasWheels;
   private boolean hasWings;
   private boolean hasBrakes;
}

MapStruct 映射器:

@Mapper(componentModel = "spring")
public interface VehicleMapper {

// Entity to DTO:
VehicleDTO toVehicleDTO(Vehicle vehicle);
List<VehicleDTO> toVehicleDTOs(List<Vehicle> vehicles);

// DTO to Entity:
Vehicle toVehicle(VehicleDTO vehicleDTO);
}

我只想完全排除值为 "false" 的布尔变量。

您可以使用 Jackson 忽略空字段。

@JsonInclude(JsonInclude.Include.NON_NULL)
public class VehicleDTO

在下面的方法中,如果值为 false,不要只在 DTO 中设置布尔字段。

// 实体到 DTO:

VehicleDTO 到 VehicleDTO(车辆车辆);

您还可以Spring BeanUtils 复制和覆盖copyProperties 方法。

public static String[] gePropertyNames(Object source) {
    final BeanWrapper wrappedSource = new BeanWrapperImpl(source);
    return Stream.of(wrappedSource.getPropertyDescriptors())
            .map(FeatureDescriptor::getName)
            .filter(propertyName -> {
                    if(wrappedSource.getPropertyValue(propertyName) != null && wrappedSource.getPropertyValue(propertyName) instanceof Boolean){
                        Boolean value = (Boolean) wrappedSource.getPropertyValue(propertyName);
                        if(value){
                            return false;
                        }else{
                            return true;
                        }
                    }else{
                        return false;
                    }
            }).toArray(String[]::new);
}

// then use Spring BeanUtils to copy and ignore properties using our function
public static void myCopyProperties(Object src, Object target) {
    BeanUtils.copyProperties(src, target, gePropertyNames(src));
}

我不确定在 MapStruct 中是否有干净的方法。一种方法是在 mapstruct 中使用表达式。我想下面的代码可能会有所帮助。

@Mapper(componentModel = "spring")
public interface VehicleMapper {

@Mapping(target = "hasWheels", expression = "java((hasWheels)?hasWheels:false)")
Vehicle toVehicle(VehicleDTO vehicleDTO);
}

但是您使用了具有 'false' 默认值的原始类型布尔变量,尽管您设置或忽略了它。

MapStruct 通过使用选项 nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS 具有 Source presence checking. By default (when an implicit conversion is happening) it checks if the source value is null before assigning it to the target. There also a way of Checking source property for null arguments 的概念,除非定义了源存在检查器,否则当源为非原始时,它将始终包含 null 检查在源 bean 上。

说了这么多。由于在您的情况下源属性是原始布尔值,因此您可以通过为这些字段添加存在性检查来实现此目的。从而消除了对表达式的需要。

例如对于 DTO

@Getter @Setter
public class VehicleDTO {

    private String name;
    private boolean hasWheels;
    private boolean hasWings;
    private boolean hasBrakes;

    public boolean hasHasWheels() {
        return hasWheels;
    }
}

有了这个,实现将首先检查 DTO 是否有 hasWheels,然后才将其设置为目标。