Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Partial implicit and partial explicit mapping of Maps - classes suported by SPI ( MapValueReader) does not work. #116

Open
slavus opened this issue Jul 30, 2014 · 1 comment

Comments

@slavus
Copy link

slavus commented Jul 30, 2014

Hi I have a problem.
I wanted to map HashMap to class. The idea was to implicitly map most key/values to class properties, and only few to explicitly map using PropertyMap.

The same thing works if I do mapping between ClassA to ClassB, but not when a do mapping between MyMap to ClassA.

Partial implicit and partial explicit mapping of Maps - classes suported by SPI - eg( MapValueReader)

I created a simple unit test that demonstrates what works, and what does and what does not work:

https://gist.github.com/slavus/25b0e269e5072e6f103f

@jhalterman
Copy link
Member

I know this issue was filed a while ago, but I wanted to respond at least for posterity based on how things work currently.

For all types, ModelMapper needs to determine which properties match to each other. It then stores this information in a TypeMap for some pair of types. For some types that are dynamic such as Maps, which properties match each other can obviously vary which can be problematic. For this reason, ModelMapper takes the first instance of the Map it encounters and uses that as a definition for how properties should be mapped for other map instances. Since maps are generic, different maps can be differentiated with different names in ModelMapper. Ex:

TypeMap<MyMap, UserDTO> typeMap = modelMapper.createTypeMap(myMap, UserDTO.class, "mymap");

This creates a TypeMap where properties are mapped based on the current contents of myMap. We give this TypeMap a unique name "mymap" to distinguish it from other possible Map to UserDTO mappings which might contain different properties. We can also chain on a call to add explicit mappings if needed:

typeMap.addMappings(
        new PropertyMap<MyMap, UserDTO>() {
          @Override
          protected void configure() {
            map().setId("42");
          }
        });

We can then perform our ModelMapper.map call passing the name of our "mymap".

UserDTO udto = modelMapper.map(myMap, UserDTO.class, "mymap");

Some possible ways we could improve things is to make explicit and implcit mappings automatically merge without having to define them in a particular order (which we do here). Another option might be to disallow the defining of internal TypeMaps completely when the source contains non-structural properties. I'm not sure how easy it would be to do this.

// TLDR;
For now, there is the above workaround: define the TypeMap first, then add your explicit mappings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants