Mapping a Collection to Map and vise versa with Mapstruct

1.9k views Asked by At

I am using Mapstruct to handle boilerplate code of mapping one POJO to another.

Here is the DTO:

import java.util.Collection;

public class TestTO {
    String name;
    Collection<AttributeTO> attributes;
}

Here is the mapped POJO:

import java.util.Map;

public class Test {
    String name;
    Map<String, Attribute> attributes;
}

I am looking for an elegant way to handle the mapping between the Map and the Collection. Currently, I am using the expression attribute of the @Mapping annotation. Since Attribute references Test I am using a CycleBreakingContext from the "mapping with cycles" example.

@Mapping(target = "attributes", expression = "java(test.getAttributes().values().stream().map(a -> this.map(a, context)).collect(java.util.stream.Collectors.toList()))")
abstract TestTO map(Test test, @Context CycleBreakingContext context);

The interface also contains a method mapping Attribute to AttributeTO with the name map.

Is there a more elegant way to implement this conversion of a non-iterable Map to a Collection? My approach is working but has it's downsides. Refactoring, for instance, does not recognise code fragments in Strings.

1

There are 1 answers

3
Patryk Krawczyk On BEST ANSWER

How about default mapper methods?

In your mapper interface you can provide default implementation instructing MapStruct on how to map given types, for example:

default Collection<Integer> mapAttributes(Map<String, Integer> attributes) {
    return attributes.values();
}

This method will be called whenever MapStruct tries to map from Map to Collection.

You are free to customize it as much as you want.