Mapstruct Mapping : Return null object if all source parameters properties are null
Asked Answered
A

2

8

I want the generated mapstruct mapping method to return null if all the properties referenced in @Mapping/source are null. For exemple, I have the following mapping :

@Mappings({
      @Mapping(target = "id", source = "tagRecord.tagId"),
      @Mapping(target = "label", source = "tagRecord.tagLabel")
})
Tag mapToBean(TagRecord tagRecord);

The generated method is then :

public Tag mapToBean(TagRecord tagRecord) {
    if ( tagRecord == null ) {
        return null;
    }

    Tag tag_ = new Tag();

    if ( tagRecord.getTagId() != null ) {
        tag_.setId( tagRecord.getTagId() );
    }
    if ( tagRecord.getTagLabel() != null ) {
        tag_.setLabel( tagRecord.getTagLabel() );
    }

    return tag_;
}

Test case : TagRecord object is not null but has tagId==null and tagLibelle==null.

Current behaviour : the returned Tag object is not null, but has tagId==null and tagLibelle==null

What I actually want the generated method to do is return a null Tag object if (tagRecord.getTagId() == null && tagRecord.getTagLabel() == null). Is it possible and how can I achieve this?

Approximal answered 13/4, 2017 at 12:11 Comment(0)
P
5

This currently is not supported from MapStruct directly. However, you can achieve what you want the help of Decorators and you will have to manually check if all the fields are empty and return null instead of the object.

@Mapper
@DecoratedWith(TagMapperDecorator.class)
public interface TagMapper {
    @Mappings({
        @Mapping(target = "id", source = "tagId"),
        @Mapping(target = "label", source = "tagLabel")
    })
    Tag mapToBean(TagRecord tagRecord);
}


public abstract class TagMapperDecorator implements TagMapper {

    private final TagMapper delegate;

    public TagMapperDecorator(TagMapper delegate) {
        this.delegate = delegate;
    }

    @Override
    public Tag mapToBean(TagRecord tagRecord) {
        Tag tag = delegate.mapToBean( tagRecord);

        if (tag != null && tag.getId() == null && tag.getLabel() == null) {
            return null;
        } else {
            return tag;
        }
    }
}

The example that I have written (the constructor) is for mappers that are with the default component model. If you need to use Spring or a different DI framework have a look at:

Prut answered 13/4, 2017 at 14:20 Comment(2)
hi Filip, is this feature added now?Alithea
Not entirely. There is a new feature added for conditional mappings, but it isn't working for method source parameters yetPrut
H
1

Now it is possible with, for example:

@BeanMapping(nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT)

That affects a method, to affect a whole class use with @Mapper

Hernardo answered 22/9, 2022 at 21:38 Comment(1)
I don't think this answers the question. nullValueMappingStrategy = RETURN_DEFAULT only says that if the input parameter is null, then an empty object. If nothing is annotated or if nullValueMappingStrategy = RETURN_NULL, then null is returned when the input parameter is null. However, the goal is to do the other way : return null when the input parameter is not null and all the fields are null.Leon

© 2022 - 2024 — McMap. All rights reserved.