How to map Map of Lists using orika?

279 views Asked by At

My source object is:

Map<Integer, List<Integer>> source = new HashMap<>();
source.put(1, Arrays.asList(1, 2, 3));
source.put(2, Arrays.asList(4, 5, 6));

How do I map it to Map<Integer, List<String>>?

I've tried:

Type<Map<Integer, List<Integer>>> sourceType = new TypeBuilder<Map<Integer, List<Integer>>>() {}.build();
Type<Map<Integer, List<String>>> destType = new TypeBuilder<Map<Integer, List<String>>>() {}.build();

// Gives empty map
Map<Integer, List<String>> intToString = mapperFacade.map(source, sourceType, destType);

// Gives map of empty lists
Map<Integer, List<String>> intToStringMap = mapperFacade.mapAsMap(source, sourceType, destType);

In the same time adding a wrapper object works fine:

class Source {
    Map<Integer, List<Integer>> value;
    // getters, setters
}
class Dest {
    Map<Integer, List<String>> value;
    // getters, setters
}

Source sourceWrapper = new Source();
sourceWrapper.setValue(source);

// Works fine: Dest(value={1=[1, 2, 3], 2=[4, 5, 6]})
Dest destWrapper = mapperFacade.map(sourceWrapper, Dest.class);

Shouldn't collections mapping be equal for top-level and nested objects?

1

There are 1 answers

0
alaster On

Ended up with a hack which I'm not happy about. Still looking for better solution.

public static <K, S, D, CS extends Collection<S>> Map<K, List<D>> mapListsMap(
        MapperFacade mapperFacade, Map<K, CS> source) {
    if (source == null)
        return null;
    Type<Wrapper<K, D, List<D>>> destinationType = new TypeBuilder<Wrapper<K, D, List<D>>>() {}.build();
    return mapperFacade.map(new Wrapper<>(source), destinationType.getRawType()).getValue();
}
    
public static class Wrapper<K, T, C extends Collection<T>> {
    private final Map<K, C> value;
    // getters, setters
}

Usage:

Map<Integer, List<Integer>> source = new HashMap<>();
source.put(1, Arrays.asList(1, 2, 3));
source.put(2, Arrays.asList(4, 5, 6));

// {1=[1, 2, 3], 2=[4, 5, 6]}
Map<Integer, List<String>> dest = Utils.mapListsMap(mapperFacade, source);