You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用ModelMapper转换嵌套对象时枚举映射失效及验证异常问题

问题原因分析

你遇到的问题核心在于:当处理嵌套对象映射时,ModelMapper并不会自动关联你手动创建的子TypeMap(也就是TypeMap<B, BDTO>),除非你明确告诉它要这么做。

你虽然创建了B -> BDTO的TypeMap,但在A -> ADTO的映射过程中,ModelMapper处理a.b这个嵌套属性时,会默认使用自己的隐式映射规则,而不是你定义好的typeMap2。这就导致typeStr没有被正确映射,同时validate()检查到BDTO.setTypeStr()没有被关联到任何源属性,所以抛出了验证异常。

解决方案

下面提供两种可行的修复方案,你可以根据自己的需求选择:

方案一:在父TypeMap中显式关联子TypeMap

修改A -> ADTO的TypeMap配置,明确指定b属性的映射要使用我们创建的B -> BDTO的TypeMap:

public static void main(String[] args) {
    A a = new A();
    B b = new B();
    b.setType(B.Type.A);
    b.setValue(34);
    a.setDay(A.Day.FRI);
    a.setB(b);

    ModelMapper modelMapper = new ModelMapper();
    modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);

    Converter<Enum, String> enumStringConverter = new AbstractConverter<Enum, String>() {
        @Override
        protected String convert(Enum source) {
            return source != null ? source.name() : null;
        }
    };

    // 先创建子TypeMap并配置映射规则
    TypeMap<B, BDTO> bTypeMap = modelMapper.createTypeMap(B.class, BDTO.class);
    bTypeMap.addMappings(m -> m.using(enumStringConverter).map(B::getType, BDTO::setTypeStr));

    // 创建父TypeMap,同时显式指定b属性的映射使用已定义的子TypeMap
    TypeMap<A, ADTO> aTypeMap = modelMapper.createTypeMap(A.class, ADTO.class);
    aTypeMap.addMappings(m -> m.using(enumStringConverter).map(A::getDay, ADTO::setDayStr));
    // 关键步骤:关联嵌套属性的映射规则
    aTypeMap.addMappings(m -> m.map(A::getB, ADTO::setB));

    System.out.println(modelMapper.map(a, ADTO.class));
    modelMapper.validate();
}

这样修改后,ModelMapper在处理A.b时会严格遵循我们预先配置好的B -> BDTO规则,typeStr就能正确映射为A,同时validate()也不会再抛出异常。

方案二:注册全局转换器(更简洁)

如果你希望所有枚举到字符串的映射都自动使用同一转换器,并且让ModelMapper自动识别嵌套对象的TypeMap,可以调整配置如下:

public static void main(String[] args) {
    A a = new A();
    B b = new B();
    b.setType(B.Type.A);
    b.setValue(34);
    a.setDay(A.Day.FRI);
    a.setB(b);

    ModelMapper modelMapper = new ModelMapper();
    modelMapper.getConfiguration()
            .setMatchingStrategy(MatchingStrategies.STRICT)
            // 注册全局枚举转字符串转换器,所有枚举转String都会自动用这个规则
            .addConverter(new AbstractConverter<Enum, String>() {
                @Override
                protected String convert(Enum source) {
                    return source != null ? source.name() : null;
                }
            });

    // 仅需指定不同名属性的对应关系,类型转换由全局转换器自动处理
    modelMapper.createTypeMap(A.class, ADTO.class)
            .addMapping(A::getDay, ADTO::setDayStr);
    modelMapper.createTypeMap(B.class, BDTO.class)
            .addMapping(B::getType, BDTO::setTypeStr);

    System.out.println(modelMapper.map(a, ADTO.class));
    modelMapper.validate();
}

这里的优势是无需手动关联嵌套TypeMap,ModelMapper会自动检测并应用已创建的B -> BDTO规则,同时全局转换器也减少了重复代码。

验证结果

修改后,控制台输出会变为:

Test.ADTO(dayStr=FRI, b=Test.BDTO(typeStr=A, value=34))

并且modelMapper.validate()不会再抛出任何异常,所有属性都完成了正确映射。

内容的提问来源于stack exchange,提问作者Alessandro Dionisi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:04:50