How could I use a HashMap<String, Object>
as source to an object?
Here is my target object:
public class ComponentStyleDTO{
private String attribute;
private Object value;
}
I've tried to use this approach that I found and that is also in the documentation, but it's failing for me.
My Mapper:
@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE, componentModel = "spring", uses = ComponentStyleMapperUtil.class)
public interface ComponentStyleMapper {
ComponentStyleMapper MAPPER = Mappers.getMapper(ComponentStyleMapper.class);
@Mappings({@Mapping(target = "attribute", qualifiedBy = ComponentStyleMapperUtil.Attribute.class),
@Mapping(target = "value", qualifiedBy = ComponentStyleMapperUtil.Value.class)})
ComponentStyleDTO hashMapToComponentStyleDTO(HashMap<String, Object> hashMap);
}
My Util:
public class ComponentStyleMapperUtil{
@Qualifier
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Attribute {
}
@Qualifier
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Value {
}
@Attribute
public String attribute(HashMap<String, Object> in){
return (String) in.entrySet().stream().findFirst().get().getKey();
}
@Value
public Object value(HashMap<String, Object> in) {
Object value = in.entrySet().stream().findFirst().get().getValue();
if(value instanceof String){
return value;
}else if(value instanceof LinkedHashMap){
List<ComponentStyleDTO> childs = new ArrayList<ComponentStyleDTO>();
HashMap<String, Object> child = (HashMap<String, Object>) value;
for(String key: child.keySet()){
ComponentStyleDTO schild = new ComponentStyleDTO();
schild.setAttribute(key);
schild.setValue((String) child.get(key));
childs.add(schild);
}
return childs;
}else{
return value;
}
}
}
And here's how I'm using this:
HashMap<String, Object> hmap = new HashMap<String, Object>();
hmap.put(attr.getKey(), attr.getValue());
ComponentStyleDTO componentDTO = componentStyleMapper.hashMapToComponentStyleDTO(hmap);
But it's returning me empty in attribute and value. Any idea of what I could be doing wrong?
Not sure what you are trying to achieve. If your mapping is more complex maybe the best way is indeed to go with the approach in https://stackoverflow.com/a/54601058/1115491.
That a side, the reason why it is not working for you is that you have not defined the source for your mapping. In the example you linked there is a POJO as source parameter and the source is a map in that POJO. In order to make it work your mapper needs to look like:
@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE, componentModel = "spring", uses = ComponentStyleMapperUtil.class)
public interface ComponentStyleMapper {
@Mapping(target = "attribute", source = "hashMap", qualifiedBy = ComponentStyleMapperUtil.Attribute.class)
@Mapping(target = "value", source = "hashMap", qualifiedBy = ComponentStyleMapperUtil.Value.class)
ComponentStyleDTO hashMapToComponentStyleDTO(HashMap<String, Object> hashMap);
}
NB: When using the non default componentModel
you should not use the Mappers
factory for getting an instance of the mapper. If you do that you will get an NPE when working with other mappers.
IMHO The best way is the simpliest way:
default ComponentStyleDTO hashMapToComponentStyleDTO(HashMap<String, Object> hashMap){
ComponentStyleDTO result = new ComponentStyleDTO();
result.setAtribute1(hashMap.get("atribute1"));
result.setAtribute2(hashMap.get("atribute2"));
result.setAtribute3(hashMap.get("atribute3"));
...
return result;
}
or
default List<ComponentStyleDTO> hashMapToComponentStyleDTO(HashMap<String, Object> hashMap){
return hashMap.entrySet()
.stream()
.map(e -> new ComponentStyleDTO(e.getKey(), e.getValue()))
.collect(Collectors.toList());
}
For future reference. As of Mapstruct 1.5 I think this usecase is supported out of the box. See mapstruct release note
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With