【问题标题】:Mapping element of a list of different type with mapstruct使用 mapstruct 映射不同类型列表的元素
【发布时间】:2019-03-31 19:38:30
【问题描述】:

我们正在映射一个对象,该对象具有一个对象列表,这些对象都实现了一个父接口,但可能有不同的实现。 但是,当我们映射列表时,似乎只映射了 ParentClass 的值,而不是 child 的值。 但直接映射孩子工作正常。

public class ParentClass{
String name;
int anotherParentField;
List<ParentClass> relation;
}

public class ChildClass1 extends ParentClass{
String customCLass1Field;
}

public class ChildClass2 extends ParentClass {
int intField;
}


public class ParentClassDto{
String name;
int anotherParentField;
List<ParentClassDto> relation;
}

public class ChildClass1Dto extends ParentClassDto{
String customCLass1Field;
}

public class ChildClass2Dto extends ParentClassDto {
int intField;
}

映射器

@Mapper
public interface ParentClassMapper{
    ParentClassDto convertToDto(ParentClass p);
    ParentClass convertDTOToModel(ParentClassDto dto);
}


@Mapper
public interface ChildClass1Mapper implements ParentClassMapper
{
    ChildClass1Dto convertToDto(ChildClass1 p);
    ChildClass1 convertDTOToModel(ChildClass1Dto dto);
}

@Mapper
public interface ChildClass2Mapper implements ParentClassMapper
{
    ChildClass2Dto convertToDto(ChildClass2 p);
    ChildClass2 convertDTOToModel(ChildClass2Dto dto);
}

如果我们将包含 ChildClass2 和 ChildClass1 的对象 ChildClass1 映射到我们得到的列表中。

要映射的对象: 对象 ChildClass1 在 json 格式中看起来像这样:

{
   "name":"myName",
   "anotherParentField":"10",
   "customCLass1Field":"custom name",
   "relation":[
      {
         (This is of Object Type : ChildClass1)
         "name":"firstRelationName",
         "anotherParentField":"110",
         "customCLass1Field":"relationcustom name"
      },
      {
         (This is of Object Type : ChildClass2)
         "name":"secondRelationName",
         "anotherParentField":"110",
         "intField":"4"
      }
   ]
}

但是当我们使用上面的映射器映射到 dto 时,我们得到:

{
   "name":"myName",
   "anotherParentField":"10",
   "customCLass1Field":"custom name",
   "relation":[
      {
         "name":"firstRelationName",
         "anotherParentField":"110",
      },
      {
         "name":"secondRelationName",
         "anotherParentField":"110",
      }
   ]
}

没有映射子类的字段。 缺少什么?

【问题讨论】:

    标签: java mapstruct


    【解决方案1】:

    除了自定义映射器之外,我没有看到其他方法。

    这是我的解决方案,他们称之为decorator

    public abstract class ParentClassMapperDecorator implements ParentClassMapper {
    
      private final ParentClassMapper delegate;
    
      public ParentClassMapperDecorator(ParentClassMapper delegate) {
        this.delegate = delegate;
      }
    
      @Override
      public ParentClass convertDTOToModel(ParentClassDto dto) {
        ParentClass parentClass = null;
    
        if (dto instanceof ChildClass1Dto) {
          parentClass = Mappers.getMapper(ChildClass1Mapper.class).convertDTOToModel((ChildClass1Dto) dto);
        } else if (dto instanceof ChildClass2Dto) {
          parentClass = Mappers.getMapper(ChildClass2Mapper.class).convertDTOToModel((ChildClass2Dto) dto);
        } else {
          parentClass = this.delegate.convertDTOToModel(dto);
        }
    
        return parentClass;
      }
    
      @Override
      public ParentClassDto convertToDto(ParentClass p) {
        // Do the job here
      }
    }
    

    并在 ParentClassMapper 中添加 @DecoratedWith 注解:

    @Mapper
    @DecoratedWith(ParentClassMapperDecorator.class)
    public interface ParentClassMapper {
    
      ParentClassDto convertToDto(ParentClass p);
    
      ParentClass convertDTOToModel(ParentClassDto dto);
    }
    

    对于孩子:

    @Mapper(uses = {ParentClassMapper.class})
    public interface ChildClass1Mapper{
    
      ChildClass1Dto convertToDto(ChildClass1 p);
    
      ChildClass1 convertDTOToModel(ChildClass1Dto dto);
    }
    
    @Mapper(uses = {ParentClassMapper.class})
    public interface ChildClass2Mapper {
    
      ChildClass2Dto convertToDto(ChildClass2 p);
    
      ChildClass2 convertDTOToModel(ChildClass2Dto dto);
    }
    

    如果你想测试:

    @Test
      public void mapStruct_Inheritance_Test() throws Exception {
    
        ChildClass1Dto childClass1Dto = new ChildClass1Dto();
        childClass1Dto.name = "name1";
        childClass1Dto.anotherParentField = 1;
        childClass1Dto.customCLass1Field = "customCLass1Field1";
    
        List<ParentClassDto> parentClassDtos = new ArrayList<>();
        ChildClass1Dto childClass11Dto = new ChildClass1Dto();
        childClass11Dto.name = "name12";
        childClass11Dto.anotherParentField = 12;
        childClass11Dto.customCLass1Field = "customCLass1Field12";
        parentClassDtos.add(childClass11Dto);
    
        ChildClass2Dto childClass21Dto = new ChildClass2Dto();
        childClass21Dto.name = "name12";
        childClass21Dto.anotherParentField = 21;
        childClass21Dto.intField = 210;
        parentClassDtos.add(childClass21Dto);
    
        childClass1Dto.relation = parentClassDtos;
    
        ParentClass parentClass = Mappers.getMapper(ParentClassMapper.class).convertDTOToModel(childClass1Dto);
      }
    

    【讨论】:

      猜你喜欢
      • 2020-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-12
      • 2021-11-28
      • 2021-12-29
      相关资源
      最近更新 更多