如何通过使用 -MapStruct 从源对象复制值来填充目标对象内的地图?

sAc*_*re. 8 java dto-mapping mapstruct

我是 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;
}
Run Code Online (Sandbox Code Playgroud)

我将如何手动实现与波纹管相同的事情:

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);
Run Code Online (Sandbox Code Playgroud)

对于直接属性映射,我找到了代码,但不确定如何映射要在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)
Run Code Online (Sandbox Code Playgroud)

任何帮助、任何建议或任何解决方法表示赞赏。提前致谢。

Fil*_*lip 5

targetMapStruct 不允许在 in 中使用表达式,这就是您无法使其工作的原因。

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

我的建议是尽可能多地使用自动映射,然后@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);
    }

}
Run Code Online (Sandbox Code Playgroud)


SKu*_*mar 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;
}
Run Code Online (Sandbox Code Playgroud)

如果地图元素太大而无法提及,可以使用 Jackson 库,它可以动态创建以引用名称作为键、对象值作为值的地图

@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);
}
Run Code Online (Sandbox Code Playgroud)