8

我是 Mapstruct 的新手。我有一个场景,在我的目标对象中,我有一个带有键值对<String,String> 的 java 映射,我必须使用源对象内部对象属性/数据成员值来填充这个映射。

我的代码类似于波纹管(虚拟代码):

public class Student {
    public String name;
    public String rollNo;
    public Map<String, String> marks;
}


public class ExamResult{

    public String stud_name;
    public String Stud_rollNo;
    public Marks marks;
}

public class Marks{
    public Integer English;
    public Integer Maths;
    public Integer Science;
}

我将如何手动实现如下相同的事情:

Student target;
ExamResult source;
target.setName(source.stud_name);
target.setRollNo(source.Stud_RollNo);
target.marks.put("ENGLISH",source.marks.english_marks);
target.marks.put("MATHS",source.marks.math_marks);
target.marks.put("SCIENCE",source.marks.science_marks);

对于直接属性映射,我找到了代码,但不确定如何映射要填充到映射中的值marks

我曾考虑过使用 java 表达式来填充目标映射值,但没有找到任何文档或此类用于目标对象的表达式示例。

我想像下面这样使用,但不确定它会起作用:

    @Mapping(source = "stud_name", target = "name")
    @Mapping(source = "Stud_RollNo", target = "rollNo")
    @Mapping(source = "source.marks.english_marks",target = "java( marks.put(\"ENGLISH\",source.marks.english_marks )")
    @Mapping(source = "source.marks.math_marks",target = "java( marks.put(\"MATHS\",source.marks.math_marks )")
    @Mapping(source = "source.marks.science_marks",target = "java( marks.put(\"SCIENCE\",source.marks.science_marks )")
Student doConvert(ExamResult src)

感谢任何帮助、任何建议或任何解决方法。提前致谢。

4

3 回答 3

5

MapStruct 不允许使用表达式target,这就是为什么你不能让它工作的原因。

还不支持从对象映射到地图,我们有不同的问题需要此功能。

我的建议是尽可能多地使用自动映射,然后@AfterMapping在 MapStruct 无法做到这一点时使用。所以在你的情况下是这样的:

@Mapper
public interface StudentMapper {

    @Mapping(source = "stud_name", target = "name")
    @Mapping(source = "Stud_RollNo", target = "rollNo")
    @Mapping(target = "marks", ignore = true) // mapped in @AfterMapping
    Student doConvert(ExamResult src)

    @AfterMapping
    default void addStudentMarks(ExamResult result, @MappingTarget Student student) {
        student.marks = new HashMap<>();
        student.marks.put("ENGLISH", result.marks.ENGLISH);
        student.marks.put("MATHS", result.marks.MATHS);
        student.marks.put("SCIENCE", result.marks.SCIENCE);
    }

}
于 2020-07-23T06:29:52.897 回答
0

我会编写一个自定义映射器方法来将标记转换为映射对象

@Mapping(source = "stud_name", target = "name")
@Mapping(source = "Stud_rollNo", target = "rollNo")
Student doConvert(ExamResult examResult);

static Map<String,String> mapMarks(Marks marks) {
    Map<String,String> marksMap = new HashMap<>();
    marksMap.put("ENGLISH", String.valueOf(marks.getEnglish()));
    marksMap.put("MATHS", String.valueOf(marks.getMaths()));
    return marksMap;
}

如果地图元素太大而无法提及,可以使用杰克逊库,它可以动态创建地图,参考名称作为键,对象值作为值

@Mapping(source = "stud_name", target = "name")
@Mapping(source = "Stud_rollNo", target = "rollNo")
Student doConvert(ExamResult examResult);

ObjectMapper mapper = new ObjectMapper();
static Map<String,String> mapMarks(Marks marks) {
    return mapper.convertValue(marks, Map.class);
}
于 2020-07-18T22:46:32.510 回答
0

那这个呢:


@Mapper
public interface MyMapper {

    @Mapping( target = "name", source = "stud_name")
    @Mapping( target = "rollNo", source = "stud_rollNo")
    // marks will be mapped based on name equality
    Student map( ExamResult result);

    // mapstruct sees an unmapped property (although it only has a getter), marks
    @Mapping( target = "marks", ignore = true )
    MarksWrapper toWrapper(Marks marks );

    // handwritten method, just to do the mapping
    default Map<String, Integer> toMap( MarksWrapper wrapper) {
        return wrapper.getMarks();
    }

    // this class does the conversion
    class MarksWrapper {

        private Map<String, Integer> marks = new HashMap<>(  );

        public void setEnglish( Integer mark) {
            marks.put( "ENGLISH", mark );
        }
        public void setMaths( Integer mark ){
            marks.put( "MATH", mark );
        }
        public void setScience( Integer mark ) {
            marks.put( "SCIENCE", mark );
        }
        public Map<String, Integer> getMarks() {
            return marks;
        }
    }
}

注意:我使用了 aMap<String,Integer> Map<String,String>但想法是一样的..

于 2020-07-24T17:41:15.213 回答