Nirley Gupta
Nirley Gupta

Reputation: 276

MapStruct Map Object to List

I am trying to use Mapstruct to map source object to a target list. What should be a clean mapstruct way of doing this?

Below are my DTO's.

Source DTO

@Data
class Source
{

String a;

String b;

String C;

}

Target DTO

@Data
class Target
{

String name;

List<Child> customList;

}

@Data
class Child
{

String attr1;

boolean attr2;

}

I am facing issues with Mapper Class. Trying to achieve something like below.

public interface CustomMapper
{

@Mapper(target="customList" expression="java(new Child(a,false))"
@Mapper(target="customList"  expression="java(new Child(b,true))"
@Mapper(target="customList"  expression="java(new Child(c,false))"
Target sourceToTarget(Source source);


}

I don't want to use qualifiedBy function like below to achieve this, as all conversion needs to be coded for each element.

List<Child> toList(Source source)
{
   List<Child> customList = new ArrayList<Child>();
   customList.add(new Child(source.getA(),false));
   customList.add(new Child(source.getB(),true)); 
   customList.add(new Child(source.getC(),false));

    return customList;
}

Upvotes: 8

Views: 36801

Answers (3)

maheeka
maheeka

Reputation: 2093

I have used an expression to solve this problem. The expression is to perform the mapping (for objects, straightforward for Strings), and then convert it to a list.

  @Mapping(target = "names", expression = "java(Arrays.asList(map(source.getName())))")
  TargetObject map(SourceObject source);
  
  TargetName map(SourceName source)

You need to import "Arrays" class in the @Mapper definition as below.

@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE, componentModel = "spring", imports = {Arrays.class})

Upvotes: 11

Niraj Sonawane
Niraj Sonawane

Reputation: 11115

I had similar use case where i want to convert and Single Object to List of objects. As these are very custom requirements, will be hard for mapstruct to provide some API for use cases like this.

I ended up implementing using default method like this

@Mapper(componentModel = "spring")
interface MyMapper {
    
    default List<SomeObject> from(SourceObject sourceObject) {
      //Add Mappig logic here 
      //return the list

    }
 }

//If you want to use some mapper for mapping

@Mapper(componentModel = "spring")
public abstract class SomeArrayMapper {

    @Autowired
    SomeMapper mapper;

    public SomeUser[] from(SingleObject singleObject) {
         SomeUsers[] Users = new SomeUser[1];
         
        Users[0] =  mapper.toUser(singleObject);;
        return Users ;
    }
}

In some cases Decorators can also be useful take a look at here

Upvotes: 6

Sjaak
Sjaak

Reputation: 4170

There is no clean way of doing this at the moment in MapStruct. MapStruct is considerring bean tot map mapping. See here: https://github.com/mapstruct/mapstruct/pull/1744 which might come in helpful once implemented.

However, if you really have a lot of properties and this is a recurring problem, and you dislike reflection - like I do - you might want to give code generation an attempt and DIY. I posted an example some while ago for generating a mapper repository here: https://github.com/mapstruct/mapstruct-examples/tree/master/mapstruct-mapper-repo but, it's a bit of an steep learning curve.. sorry

Upvotes: 2

Related Questions