Search code examples
javajsonspringspring-bootmodelmapper

How to use TypeMap in ModelMapper


I have a situation in which the json payload changes if the value is null.

For example the following date object has three objects(year, month, day). If there is no data like in "day", 'value' will not show and it will just be null.

"date":{
  "year":{
     "value":"2021"
  },
  "month":{
     "value":"09"
  },
  "day":null
 }

I had a bunch of if conditions throughout to check for these nulls but that didn't look good.

So now I'm looking into using ModelMapper.

This is what I have so far. I thought that some of the properties out of the box would handle null but I guess not since the payload changes when null.

private static MyDto mapData(Info info) {

ModelMapper modelMapper = new ModelMapper();   // relace -- MyCustomizedMapper

modelMapper.getConfiguration()
.setMatchingStrategy(MatchingStrategies.STRICT)
.setDeepCopyEnabled(true)
.setPropertyCondition(Conditions.isNotNull());

var mappedDto = modelMapper.map(info, MyDto.class);
mappedDto.setDay(info.getDay().getValue());
}
return mappedDto 

//nullPointerException is thrown because getDay is null 

So then I tried using a customized mapper that checks for null.

public class MyCustomizedMapper extends ModelMapper{

@Override
public <D> D map(Object source, Class<D> destinationType) {
 Object tmpSource = source;
  if(source == null){
  tmpSource = new Object();
  }
  return super.map(tmpSource, destinationType);
 }
}

but I still get a null pointer exception.

I ran across this piece of code on the model mapper site and now trying to use when(notNull) condition.

  typeMap.addMappings(mapper -> mapper.when(notNull).map(Person::getName, PersonDTO::setName));

Attempting to use TypeMap here...

TypeMap<Info, MyDto> typeMap =
    modelMapper.createTypeMap(Info.class, MyDto.class);

// Define the mappings on the type map
typeMap.addMappings(mapper -> {
  mapper.map(src -> src.getDay(),
      MyDto::setDay);
  mapper.when(Conditions.isNotNull()).skip(MyDto::setDay);
});

Error: Source properties must be provided when conditional skip, please use when().skip(sourceGetter, destinationSetter) instead

How do I use ModelMapper correctly in this situation?


Solution

  • You should simply configure the Conditional mapping to apply only when the isNotNull condition is matched:

    TypeMap<Info, MyDto> typeMap = modelMapper.createTypeMap(Info.class, MyDto.class);
    typeMap.addMappings(mapper -> {
        mapper.when(Condition.isNotNull()).map(Info::getDay, MyDto::setDay);
    });