ModelMapper set destination field to `null` instead of throwing `MappingException`

172 Views Asked by At

I'm using a ModelMapper to convert objects from a third party api to my internal system. The data quality of this api is horrible and i'm not willing to lower mine just for that.

So many fields that should be a Short or a Byte, many times come as high values [like long]
many fields that should be strictly númeric sometimes come with strings...

this causes my model mapper being unable to map said fields and throwing MappingException

The exception itself doesn't let me know what field failed to map, just says that:

org.modelmapper.MappingException: ModelMapper mapping errors:

1) Value '227911' is too large for java.lang.Short

1 error

I would like to make model mapper ignore said fields, setting the destination value for null when such error happens and continuing trying to map other available fields...

is there any easy way to do this?

1

There are 1 best solutions below

0
Per Huss On

You can do it like this (if good or not is a matter of opinion): Create your own converter for Numbers that suppresses conversion issues and then replace the default one with yours. I have used Lombok to simplify the converter.

An UnsafeNumberConverter that delegates to to the default one could look like this ...

@AllArgsConstructor
class UnsafeNumberConverter implements ConditionalConverter<Object, Number> {

    @Delegate private ConditionalConverter<Object, Number> delegate;

    @Override
    public Number convert(MappingContext<Object, Number> context) {
        try {
            return delegate.convert(context);
        } catch (MappingException e) {
            // Ignore any number conversion issues
            return null;
        }
    }
}

... and to replace the default NumberConverter with that one you could use...

    ModelMapper modelMapper = new ModelMapper();
    InheritingConfiguration config = (InheritingConfiguration) modelMapper.getConfiguration();
    ConditionalConverter<Object, Number> converter =
            config.converterStore.getFirstSupported(Object.class, Number.class);
    config.getConverters().remove(converter);
    config.getConverters().add(new UnsafeNumberConverter(converter));