mapstruct icon indicating copy to clipboard operation
mapstruct copied to clipboard

Conditional mapping by group

Open onacit opened this issue 11 months ago • 1 comments

Use case

Can we have a specific annotation for conditional mapping?

class PersonDto {

    @MapOn({
            ValidationGroup.Create.class
    })
    @NotBlank({
            ValidationGroup.Create.class
    })
    private String name; // not gonna changed once inserted

    @MapOn({
            ValidationGroup.Create.class,
            ValidationGroup.Update.class
    })
    @NotBlank({
        ValidationGroup.Create.class,
        ValidationGroup.Update.class
    })
    private String address; // may be updated whenever moved
}
class PersonEntity {

    @Column(name = "name", nullable = false, insertable = true,
        updatable = false // <<<<<<<<<<<<<<<<<<<<<<<<<<<
    )
    private String name;

    @Column(name = "address", nullable = false, insertable = true, 
        updatable = true // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    )
    private String address;
}
public interface _BaseEntityTypeMapper<T extends _BaseEntityType<T>, U extends _BaseEntity<U>>
        extends __BaseTypeMapper<T> {

    U mapToEntity(T source, @MappingTarget U target, Class<?>... groups);

class PeopleController {

    void create(@Validated(ValidationGroup.Create.class) PersonDto personDto) {
        // maps name and address
        PersonEntity entity = personMapper.mapToEntity(personDto, new PersonEntity(), ValidationGroup.Create.class);
    }

    void update(@Validated(ValidationGroup.Update.class) PersonDto personDto) {
        PersonEntity personEntity = findById(0L);
        // maps `address` only
        PersonEntity entity = personMapper.mapToEntity(personDto, personEntity, ValidationGroup.Update.class);
    }
}

Generated Code

No response

Possible workarounds

No response

MapStruct Version

No response

onacit avatar Apr 28 '25 06:04 onacit

@onacit how do you envision the generated mapping code to look like?

I believe that it is possible to already achieve what you are looking for using the existing @Condition annotation.

You'll need to write something like:

@Condition
public boolean shouldMap(@TargetPropertyName String propertyName, @MappingTarget Object target, @Context Class<?>... groups) {
    // provide your implementation
}

Your mapping method should then look like:

U mapToEntity(T source, @MappingTarget U target, @Context Class<?>... groups);

filiphr avatar May 10 '25 17:05 filiphr