Search code examples
javamappingmodelmapper

ModelMapper: Incorect property mapping from null objects


I'm trying to map source object which property is set to null to destination object of which this property is set to another object.

Expected result would be that property of destination object will be null after mapping. Instead of that, this property is set to an object and all of its properties are set to null.

Here is an example:

public class ModelMapperTest {
    public static void main(String[] args) {
        ModelMapper modelMapper = new ModelMapper();

        User user = new User();
        user.setStatus(null);

        StatusDto statusDto = new StatusDto();
        statusDto.setId(1);
        statusDto.setName("Active");

        UserDto userDto = new UserDto();
        userDto.setStatus(statusDto);

        // user.status=null, userDto.status=StatusDto(id=1, name="Active")
        modelMapper.map(user, userDto);

        System.out.println("user = " + user);
        System.out.println("userDto = " + userDto);
    }    

    @Getter
    @Setter
    @ToString
    public static class User {
        private Status status;
    }

    @Getter
    @Setter
    @ToString
    public static class Status {
        private Integer id;
        private String name;
    }

    @Getter
    @Setter
    @ToString
    public static class UserDto {
        private StatusDto status;
    }

    @Getter
    @Setter
    @ToString
    public static class StatusDto {
        private Integer id;
        private String name;
    }
}

Output:

user = ModelMapperTest.User(status=null)
userDto = ModelMapperTest.UserDto(status=ModelMapperTest.StatusDto(id=null, name=null))

Is it possible to somehow configure model mapper to sets UserDto.status to null?


Solution

  • I know this is an older question and you seem to have moved on to a different library, but I had the same problem recently and came up with this solution (building on your example):

      Converter<?, ?> preserveNullConverter = (context) ->
         context.getSource() == null
            ? null
            : modelMapper.map(context.getSource(), context.getDestinationType());
    
      modelMapper.createTypeMap(User.class, UserDto.class)
         .addMappings(mapper -> mapper.using(preserveNullConverter).map(User::getStatus, UserDto::setStatus));
    

    It's not ideal because the .addMappings part needs to be done for every property where the issue occurs, but at least the Converter can be reused.