mapstruct / mapstruct-examples

Examples for using MapStruct
Other
1.28k stars 511 forks source link

Mapper array to List example #121

Open hualmeid opened 3 years ago

hualmeid commented 3 years ago

Hi,

Would be nice to have an example that shows the usage of MapStruct with array (like int[] ) to immutable list with specific add and addAll (like in protobuf).

example: proto file

    message UserDTO {
        string id = 1;
        string email = 2;
        repeated PermissionDTO permissions = 3;
        repeated DepartmentDTO main_departments  = 4;
        repeated DepartmentDTO departments  = 5;
    }

java file

 public class User {

     private String id;
     private String email;
     private Permission[] permissions = new Permission[0];
     private List<Department> mainDepartments = new ArrayList<>();
     private List<Department> departments = new ArrayList<>();

     public String getId() {
         return id;
     }

     public void setId(String id) {
         this.id = id;
     }

     public String getEmail() {
         return email;
     }

     public void setEmail(String email) {
         this.email = email;
     }

     public Permission[] getPermissions() {
         return permissions;
     }

     public void setPermissions(Permission[] permissions) {
         this.permissions = permissions;
     }

public List<Department> getDepartments() {
    return departments;
}

public void setDepartments(List<Department> departments) {
    this.departments = departments;
}

public List<Department> getMainDepartments() {
    return mainDepartments;
}

public void setMainDepartments(List<Department> mainDepartments) {
    this.mainDepartments = mainDepartments;
}
 }

Mapper

 @Mapper(collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED,
         nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS)
 public interface UserMapper {

     UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);

     @Mapping(source = "permissions", target = "permissionsList")
     @Mapping(source = "mainDepartments", target = "mainDepartmentsList")
     @Mapping(source = "departments", target = "departmentsList")
     UserDTO map(User user);
 }

Error: Can't map property "Permission[] permissions" to "PermissionDTO permissionsList".

### Desired solution:

 public class UserMapperImpl implements UserMapper {

     @Override
     public UserDTO map(User user) {
         if ( user == null ) {
             return null;
         }

         Builder userDTO = UserDTO.newBuilder();

         if ( user.getPermissions() != null ) {
             for ( Permission permission : user.getPermissions() ) {
                 userDTO.addPermissions( map( permission ) );
             }
         }

        ...

         return userDTO.build();
     }
 }

or

 public class UserMapperImpl implements UserMapper {

     @Override
     public UserDTO map(User user) {
         if ( user == null ) {
             return null;
         }

         Builder userDTO = UserDTO.newBuilder();

         if ( user.getPermissions() != null ) {
             userDTO.addAllPermissions( map( user.getPermissions()) );
         }

        ...

         return userDTO.build();
     }
 }

Is it possible to do this with actual release?

filiphr commented 3 years ago

Hey @hualmeid,

The issue list is not meant for asking questions, if you need to ask a question then please use StackOverflow.

Mapping between an array and List should work, so I would suggest to first try without protobuf and then see why it doesn't work with protobuf. If it is not working without protobuf please raise an issue in the mapstruct project.

seime commented 3 years ago

@hualmeid you might also want to have a look at https://github.com/entur/mapstruct-spi-protobuf for the protobuf part - no need to add specific mappings for repeated elements (which generates Lists in protobuf)

filiphr commented 3 years ago

Good point @seime, thanks for pointing it out. Btw @seime if you want we could add the mapstruct-spi-protobuf in the MapStruct Documentation, feel free to add a PR