如何将自定义映射添加到现有的 mapStruct 映射器?

How to add custom mapping to an existing mapStruct mapper?

所以我的这位同事创建了一个简单的映射器,我想为其添加更多功能。 我怀疑 mapStruct 将无法为其自动生成方法,因此我相信我将不得不编写自定义映射逻辑。我想将嵌套在输入对象中并保存在键值对结构中的值映射到输出的属性。

  1. 我假设我需要编写自定义映射器是否正确?
  2. 我可以将我的自定义映射逻辑附加到他现有的直接映射器吗?
  3. 还是我必须用新的自定义映射器完全替换他的映射器?

这是手头结构的一个例子。 他为成员一、二、三实现了映射,我想为成员alpha和beta添加映射。

@Mapper()
public interface AMapper {
    @Mapping(source = "one", target = "oneX")
    @Mapping(source = "two", target = "twoX")
    @Mapping(source = "three", target = "threeX")
    OutA inAToOutA(InA inA);
}

class InA {
    String one;
    int two;
    long three;
    InB b;
}

class InB {

    List<InC> listOfC = new ArrayList<>();
    
    public InB() {
        listOfC.add(new InC("alpha", "AlphaContent"));
        listOfC.add(new InC("beta", "BetaContent"));
    }
}


class InC {
    String key;
    String value;
    
    public InC(String key, String value) {
        this.key = key;
        this.value = value;
    }
}

class OutA {
    String oneX;
    int twoX;
    long threeX;
    String alphaX;
    String betaX;
}

在我的 mapStruct 菜鸟头脑中,解决方案可能看起来像这样, 但我宁愿不必重写他所有的东西,因为它比这个例子更大, 这就是我征求意见的原因:

@Mapper()
public interface AMapper {
    default OutA getA(InA a) {
        if (a == null)
            return null;
        OutA oa = new OutA();
        oa.setOneX(a.getOne());
        oa.setTwoX(a.getTwo());
        oa.setThreeX(a.getThree());
        for (InC c : a.getB().getListOfC()) {
            switch (c.getKey()) {
                case "alpha":
                    oa.setAlphaX(c.getValue());
                    break;
                case "beta":
                    oa.setBetaX(c.getValue());
                    break;
                default:
                    break;
            }
        }
        return oa;
    }
}

您可以在现有映射器中使用 mapstruct @AfterMapping 注释:

@Mapper
public interface AMapper {

    @Mapping(source = "one", target = "oneX")
    @Mapping(source = "two", target = "twoX")
    @Mapping(source = "three", target = "threeX")
    @Mapping(target = "alphaX", ignore = true)
    @Mapping(target = "betaX", ignore = true)
    OutA inAToOutA(InA inA);


    @AfterMapping
    default void afterMappingInAtoOutA(@MappingTarget OutA outA, InA inA) {

        if (inA.getB() == null || inA.getB().getListOfC() == null) { // add some null cheсks
            return;
        }

        for (InC c : inA.getB().getListOfC()) {
            switch (c.getKey()) {
                case "alpha":
                    outA.setAlphaX(c.getValue());
                    break;
                case "beta":
                    outA.setBetaX(c.getValue());
                    break;
                default:
                    break;
            }
        }
    }
}