MapStruct: mapping from java.util.Map to Bean?
Asked Answered
P

2

13

I currently have a Map<String, String> that contains values in the form key = value and I would like to "expand" those into a real object.

Is it possible to automate that with MapStruct and how would I do that?

To clarify: The code I would write by hand would look something like this:

public MyEntity mapToEntity(final Map<String, String> parameters) {
  final MyEntity result = new MyEntity();
  result.setNote(parameters.get("note"));
  result.setDate(convertStringToDate(parameters.get("date")));
  result.setCustomer(mapIdToCustomer(parameters.get("customerId")));
  // ...
  return result;
}
Perpetrate answered 14/2, 2017 at 12:59 Comment(1)
I think that currently this is not possible in MapStruct. However, it looks interesting. Can you create an issue in the MapStruct issue tracker as a new feature that might be added if people are interested in it.Holly
T
13

Method 1

The MapStruct repo gives us useful examples such as Mapping from map.

Mapping a bean from a java.util.Map would look something like :

@Mapper(uses = MappingUtil.class )
public interface SourceTargetMapper {

    SourceTargetMapper MAPPER = Mappers.getMapper( SourceTargetMapper.class );

    @Mappings({
        @Mapping(source = "map", target = "ip", qualifiedBy = Ip.class),
        @Mapping(source = "map", target = "server", qualifiedBy = Server.class),
    })
    Target toTarget(Source s);
}

Notice the use of the MappingUtil class to help MapStruct figuring out how to correctly extract values from the Map :

public class MappingUtil {

    @Qualifier
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.SOURCE)
    public @interface Ip {
    }

    @Qualifier
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.SOURCE)
    public static @interface Server {
    }

    @Ip
    public String ip(Map<String, Object> in) {
        return (String) in.get("ip");
    }

    @Server
    public String server(Map<String, Object> in) {
        return (String) in.get("server");
    }
}

Method 2

As per Raild comment on the issue related to this post, it is possible to use MapStruct expressions to achieve similar results in a shorter way :

@Mapping(expression = "java(parameters.get(\"name\"))", target = "name")
public MyEntity mapToEntity(final Map<String, String> parameters);

No note on performance though and type conversion may be trickier this way but for a simple string to string mapping, it does look cleaner.

Trooper answered 8/1, 2018 at 15:12 Comment(0)
M
8

Since version 1.5.0.Beta1 (Jul 2021) MapStruct supports mapping from Map to POJO.

Example:

@Mapper
public interface CustomerMapper {
    @Mapping(target = "name", source = "customerName")
    Customer toCustomer(Map<String, String> map);
}
Marcelline answered 21/10, 2021 at 6:3 Comment(2)
How to map in the opposite direction?Bubbler
@Bubbler I'm not sure that MapStruct supports that. Fastest solution that came to my mind is using fasterxml ObjectMapper - serialize POJO to JsonObject (witch in fact is a Map)Marcelline

© 2022 - 2024 — McMap. All rights reserved.