Home > Software design >  MapStruct for mapping nested class objects and list object
MapStruct for mapping nested class objects and list object

Time:07-31

I am trying to use MapStruct for a structure similar to the following:

Source:

public class ClassSource{
  private int id;
  private String name;
  private String numT; 
  private List<CustAddress> addresses = null;
  private Person person;
}

public class CustAddress implements Serializable {
  @JsonProperty("postalCode")
  private String postalCode;
}

public class Person implements Serializable {
  @JsonProperty("jobTitle")
  private String jobTitle;
}

Destination :

 public class ClassDestination {
  private int id;
  private String name;
  private String numT;
  private List<CustAddress> addresses = null;
}

public class CustAddress implements Serializable {
  @JsonProperty("zipCode")
  private String zipCode;
}

public class Person implements Serializable {
  @JsonProperty("workTitle")
  private String workTitle;
}

want to achieve the below mapping from Address list postalcode to destination address list zipcode and Person jobTitle on the subclass to target Person workTitle

 public interface PersonMapper {
  @Mapping(source = "addresses.postalCode", target = "addresses.zipCode")
  @Mapping(source = "person.jobTitle", target = "person.workTitle")
 ClassDestination  map(ClassSource source);

The above @mapping not referring the subclass properly from source to destination.. it's throwing exceptions

CodePudding user response:

  @Getter
  @Setter
  @Builder
  static class ClassSource {
    private int id;
    private String name;
    private String numT;
    private List<AddressSource> addresses;
    private PersonSource person;
  }

  @Getter
  @Setter
  @Builder
  static class AddressSource implements Serializable {
    @JsonProperty("postalCode")
    private String postalCode;
  }

  @Getter
  @Setter
  @Builder
  static class PersonSource implements Serializable {
    @JsonProperty("jobTitle")
    private String jobTitle;
  }

  @Getter
  @Setter
  @Builder
  @ToString
  static class ClassDestination {
    private int id;
    private String name;
    private String numT;
    private List<AddressDestination> addresses;
    private PersonDestination person;
  }

  @Getter
  @Setter
  @Builder
  @ToString
  static class AddressDestination implements Serializable {
    @JsonProperty("zipCode")
    private String zipCode;
  }

  @Getter
  @Setter
  @Builder
  @ToString
  static class PersonDestination implements Serializable {
    @JsonProperty("workTitle")
    private String workTitle;
  }

  @Mapper(uses = {AddressMapper.class})
  interface ClassMapper {
    @Mapping(source = "person.jobTitle", target = "person.workTitle")
    ClassDestination sourceToDestination(ClassSource source);
  }

  @Mapper
  interface AddressMapper {
    @Mapping(source = "postalCode", target = "zipCode")
    AddressDestination sourceToDestination(AddressSource source);
  }

  private static final ClassMapper classMapper = Mappers.getMapper(ClassMapper.class);

  public static void main(String[] args) {
    PersonSource personSource = PersonSource.builder().jobTitle("Dev").build();
    List<AddressSource> addressSources =
        List.of(
            AddressSource.builder().postalCode("412101").build(),
            AddressSource.builder().postalCode("411001").build());
    ClassSource classSource =
        ClassSource.builder()
            .id(1)
            .name("Firstname")
            .numT("2")
            .addresses(addressSources)
            .person(personSource)
            .build();

    ClassDestination classDestination = classMapper.sourceToDestination(classSource);
    System.out.println(classDestination);
  }

I created a temp scenario locally. I have used an additional mapper for mapping nested objects. This should work.

CodePudding user response:

This might be your problem:

@Mapping(source = "addresses.postalCode", target = "addresses.zipCode").

addresses is a List, if doesn't have a zipCode field. You need to declare a single method for person to declare that mapping,

public interface AddressMapper {
 @Mapping(source = "person.jobTitle", target = "person.workTitle")
 ClassDestination  map(ClassSource source);

 @Mapping(source = "postalCode", target = "zipCode")
 destination.Address mapPerson(source.Address);
}
  • Related