How can I convert String to Map using MapStruct?

10,335

Solution 1

Thank you guys for answers. Found the easiest solution for me by adding few manual mappers to MapStruct's StoryMapper interface.

// Manual convert to Map
default Map toMap(String text){
    Map map = new HashMap();
    try {
        map = new ObjectMapper().readValue(text, new TypeReference<Map<String, String>>(){});
    } catch (IOException e) {
        e.printStackTrace();
    }

    return map;
}

// Manual convery from map
default String fromMap(Map map){
    return new JSONObject(map).toString();
}

Solution 2

Try following code, inspired from here

@Mapper(componentModel = "spring")
public interface StoryMapper {

      @Mappings({
        @Mapping(source = "storyInfo", target = "storyInfo", qualifiedByName = "fromJsonToMap")
      })
      StoryDTO toStoryDTO(Story story);

      @Mappings({
        @Mapping(source = "storyInfo", target = "storyInfo", qualifiedByName = "fromMapToJson")
      })
      Story toStory(StoryDTO storyDTO);

      @Named("fromJsonToMap")
      default Map<String, Object> fromJsonToMap(String storyInfo) throws IOException {
        if (Objects.nonNull(storyInfo)) {
            ObjectMapper objectMapper = new ObjectMapper();
            Map<String, Double> result = objectMapper.readValue(storyInfo, new TypeReference<Map<String, Object>>() {});
            return result;
        }
        return null;
      }

      @Named("fromMapToJson")
      default String fromMapToJson(Map<String, Object> storyInfo) throws JsonProcessingException {
        if (Objects.nonNull(storyInfo)) {
            ObjectMapper objectMapper = new ObjectMapper();
            String result = objectMapper.writeValueAsString(storyInfo);
            return result;
        }
        return null;
      }

}

Solution 3

The already provided answer explains well how you can provide a Service to do the mapping with Jackson.

In order to make this work with MapStruct you can use qualifiers and annotate your service accordingly.

For example

@Qualifier // from the MapStruct package
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface FromJson {
}

public interface StringToMapConverter {

    @FromJson
    Map<String, String> convert(String string);
}

@Mapper(componentModel = "spring")
public interface MyMapper {

    @Mapping(target = "storyInfo", qualifiedBy = FromJson.class)
    StoryDTO convert(Story story);
}

The implementation of StringToMapConverter should be as in the already provided answer. You don't have to use a dedicated interface for the converter, you an also use an abstract mapper, inject the ObjectMapper and do the rest same.

MapStruct will then use it to convert the storyInfo String into the map.

Some other possible solution, outside of the scope of the question and if you use Hibernate. You can use Map<String, String> in your entity, but still map it to String in the DB. Have a look at hibernate-types by Vlad Mihalcea, it allows using extra types so you can persist objects as JSON in the database

Share:
10,335
John Salazar
Author by

John Salazar

Updated on June 14, 2022

Comments

  • John Salazar
    John Salazar almost 2 years

    I have Story entity in my Spring Boot application. It has String field storyInfo which contains:

    {"title":"random title", "description":"random description"}
    

    For my Story entity I have StoryDTO with map field called storyInfo. The question is: how can I convert String field from Strory into Map in StoryDTO using MapStruct?

  • Filip
    Filip over 6 years
    I have provided a MapStruct approach. You can have a look at it and update your answer accordingly. Your answer is completely OK, and the OP would need to implement something like that so the string can be eventually converted