user6440081
user6440081

Reputation:

MapStruct: exclude property based on (boolean) value

I'm aware that MapStruct can ignore unmapped properties and specific target properties, but is it possible to exlcude a property based on its actual value?

I have boolean fields which I would like to exclude only if they are false.

Thanks in advance!

Example:

Entity:

@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:

@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);
}

I would like to fully exclude the boolean variables only if their value is "false".

Upvotes: 1

Views: 3840

Answers (3)

Filip
Filip

Reputation: 21403

MapStruct has the concept of 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 by using the the option nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS, which will always include a null check when source is non primitive, unless a source presence checker is defined on the source bean.

Having said all this. Since in your case the source properties are primitive boolean, you can achieve this by adding a presence check for those fields. Thus eliminating the need for an expression.

e.g. for the DTO

@Getter @Setter
public class VehicleDTO {

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

    public boolean hasHasWheels() {
        return hasWheels;
    }
}

With this the implementation would first check if the DTO has hasWheels and only then set it to the target.

Upvotes: 0

dassum
dassum

Reputation: 5103

You can use Jackson to ignore the null fields.

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

In the below method don't just set the Boolean fields in DTO if the value is false.

// Entity to DTO:

VehicleDTO toVehicleDTO(Vehicle vehicle);

You can also Spring BeanUtils to copy and override copyProperties method.

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));
}

Upvotes: 0

Kaushik
Kaushik

Reputation: 56

I am not sure if there is a clean way to do in MapStruct. One way is to use expressions in mapstruct. I guess the below code might help.

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

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

However you have used primitive type boolean variables which has 'false' default value though u set or ignore it.

Upvotes: 1

Related Questions