2

I am trying to use ModelMapper to map a collection of sub-objects to a list of id numbers.

public class Child {
    private int id;
    private String childName;
}

public class Parent {
    private Set<Child> children;
    private String parentName;
}

public class ParentDto {
    private int[] children; // Or use ArrayList<Integer>
    private String parentName;
}

How do I tell ModelMapper to flatten the set of Child objects to an array of id numbers?

My first attempt is this but does not seem correct:

    modelMapper.addMappings(new PropertyMap<Parent, ParentDto>() {
        @Override
        protected void configure() {
            using(ctx -> ctx.getSource().stream().map(Parent::getId).collect(Collectors.toList())
                .map().setChildren(source.getId()));
        };
    });


    Type listType = new TypeToken<ArrayList<ParentDto>>() {}.getType();
    ArrayList<ParentDto> parentDtos = new ArrayList<>();
    parentDtos = modelMapper.map(parents, listType);

The setChildren call seems like it needs to be map().add() but that does not work either.

Ideas are welcome.

Naman
  • 27,789
  • 26
  • 218
  • 353
rboarman
  • 8,248
  • 8
  • 57
  • 87

1 Answers1

4

One way of doing this is to create a Set<Child> to int[] converter and use it to map Parent.children to ParentDTO.children:

ModelMapper mapper = new ModelMapper();

Converter<Set<Child>, int[]> childSetToIntArrayConverter =
        ctx -> ctx.getSource()
                .stream()
                .mapToInt(Child::getId)
                .toArray();

mapper.createTypeMap(Parent.class, ParentDto.class)
        .addMappings(map -> map
                .using(childSetToIntArrayConverter)
                .map(
                        Parent::getChildren,
                        ParentDto::setChildren
                )
        );

Here is the complete demo (using lombok 1.18.10 and modelmapper 2.3.5):

import lombok.AllArgsConstructor;
import lombok.Data;
import org.modelmapper.Converter;
import org.modelmapper.ModelMapper;

import java.util.Set;

public class Main {

    public static void main(String[] args) {

        Parent parent = new Parent();
        parent.setParentName("Parent");
        parent.setChildren(Set.of(
                new Child(1, "A"),
                new Child(2, "B"),
                new Child(3, "C")
        ));

        ModelMapper mapper = new ModelMapper();

        Converter<Set<Child>, int[]> childSetToIntArrayConverter =
                ctx -> ctx.getSource()
                        .stream()
                        .mapToInt(Child::getId)
                        .toArray();

        mapper.createTypeMap(Parent.class, ParentDto.class)
                .addMappings(map -> map
                        .using(childSetToIntArrayConverter)
                        .map(
                                Parent::getChildren,
                                ParentDto::setChildren
                        )
                );

        ParentDto dto = mapper.map(parent, ParentDto.class);

        System.out.println(parent);
        System.out.println(dto);
    }

    @Data
    @AllArgsConstructor
    public static class Child {
        private int id;
        private String childName;
    }

    @Data
    public static class Parent {
        private Set<Child> children;
        private String parentName;
    }

    @Data
    public static class ParentDto {
        private int[] children;
        private String parentName;
    }
}

Output

Main.Parent(children=[Main.Child(id=3, childName=C), Main.Child(id=2, childName=B), Main.Child(id=1, childName=A)], parentName=Parent)
Main.ParentDto(children=[3, 2, 1], parentName=Parent)
MartinBG
  • 1,500
  • 13
  • 22