Can't use `@Mapping#source` for map keys containg the dot character
Expected behavior
Using the new map->bean mapping feature it is not possible to use @Mapping#source for keys containing a . character. Instead, the Map type itself seems to be considered as the source type and its methods are proposed as alternatives.
It's still possible to achieve that with expression of course (as in the commented out line in the example), but it's far less elegant as just using the source.
Actual behavior
error: No property named "a.b" exists in source parameter(s). Did you mean "a.bytes"?
@Mapping(target = "value", source = "a.b")
Steps to reproduce the problem
package com.example;
import org.junit.jupiter.api.Test;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
class MapstructExampleTest {
public static record ExampleBean(String value) { }
@Mapper
public interface ExampleMapper {
@Mapping(target = "value", source = "a.b")
//@Mapping(target = "value", expression = "java(source.get(\"a.b\"))")
ExampleBean map(Map<String, String> source);
}
@Test
void shouldMapToBean() {
Map<String, String> source = Map.of("a.b", "test");
var output = Mappers.getMapper(ExampleMapper.class).map(source);
assertThat(output.value()).isEqualTo("test");
}
}
MapStruct Version
1.5.3
Hi, I guess you can take a look at this document
Thank you, I have of course read through the documentation and described behavior seems to contradict what's written there:
using the target bean properties (or defined through Mapping#source) to extract the values from the map
The example even shows usage of Mapping#source to directly name the field in the source map from which a value should be taken. There's no mention here of the . character being treated in a special way as it is for bean mappings - but in that case, it's used to support nested beans and the characters can't be used in a field name anyway. For String map keys it's no longer a special character and unless there is a plan to have support for multi-level maps as mapping sources, there's no point in having any special handling for it. Furthermore, the error message suggests the Map type itself is treated as source type (as opposed to map contents), which also supports the idea that this is not intended behavior.
I think you are right, we may need to think about how to handle the dot character in map in a special way
Hi, are there any updates on this?
Hi, are there any updates on this?
As sajkol wrote above, you can use the expression attribute of the Mapping annotation to do a bit of it
e.g.
@Mapper
public interface ExampleMapper {
@Mapping(target = "value", expression = "java(source.get( \"a.b\" ))")
ExampleBean map(Map<String, String> source);
}
will generate
public class ExampleMapperImpl implements ExampleMapper {
@Override
public ExampleBean map(Map<String, String> source) {
if ( source == null ) {
return null;
}
ExampleBean exampleBean = new ExampleBean();
exampleBean.setValue( source.get( "a.b" ) );
return exampleBean;
}
}