3

I need to convert an object of Map<String,String> with keys like "some_att_name" to class object fields like someAttName.

I couldn't find an easy way to do this. MapStruct does support this type of mapping (From Map to object) since v1.5.0.Beta1 as stated here.

What I want should look something like this (similar to how JSON converters work):

@Mapper
public interface MapToObjectMapper {

    MapToObjectMapper INSTANCE = Mappers.getMapper(MapToObjectMapper.class);

    @Mapping(strategy = SnakeCaseToCamelCaseStrategy.class)
    MyObject toMyObject(Map<String,String> map);

}
Nom1fan
  • 846
  • 2
  • 11
  • 27

2 Answers2

3

You'll have to translate the keys by yourself, but that's not that hard. Here is how I do it:

import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;

import java.util.Collections;
import java.util.Map;
import java.util.regex.Pattern;

import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.toMap;

@Mapper
public interface MapToObjectMapper {
    MapToObjectMapper INSTANCE = Mappers.getMapper(MapToObjectMapper.class);

    private static String snakeToCamel(String snakeCaseString) {
        // You can use Guava, Apache Commons, write it yourself or just use this one
        // Credits to https://stackoverflow.com/a/67605103/4494577
        return Pattern.compile("_([a-z])")
                .matcher(snakeCaseString)
                .replaceAll(m -> m.group(1).toUpperCase());
    }

    MyObject toMyObject(Map<String, String> map);

    default MyObject toMyObjectFromSnakeCaseMap(Map<String, String> snakeKeyPropertyMap) {
        return toMyObject(snakeKeyPropertyMap.entrySet().stream()
                .collect(collectingAndThen(
                        toMap(s -> snakeToCamel(s.getKey()), Map.Entry::getValue),
                        Collections::unmodifiableMap)));
    }
}

Full example: https://github.com/jannis-baratheon/stackoverflow--mapstruct-snake-case-map-mapping/

jannis
  • 4,843
  • 1
  • 23
  • 53
1

Looking at the docs I can't see a 1 step mapping. I think referring to From snake_case to camelCase in Java for converting your Map's keys to camelCase and then going for a mapper without @Mapping annotations might be your best chance.