Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MapStruct Map Object to List

Tags:

java

mapstruct

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;
}
like image 911
Nirley Gupta Avatar asked Jul 28 '19 18:07

Nirley Gupta


People also ask

How do you map a list of objects using MapStruct?

In general, mapping collections with MapStruct works in the same way as for simple types. Basically, we have to create a simple interface or abstract class and declare the mapping methods. Based on our declarations, MapStruct will generate the mapping code automatically.

How MapStruct works?

MapStruct is an open-source Java-based code generator which creates code for mapping implementations. It uses annotation-processing to generate mapper class implementations during compilation and greatly reduces the amount of boilerplate code which would regularly be written by hand.

How do I ignore mapping in MapStruct?

To do this, we use the MapStruct unmappedTargetPolicy to provide our desired behavior when there is no source field for the mapping: ERROR: any unmapped target property will fail the build – this can help us avoid accidentally unmapped fields. WARN: (default) warning messages during the build. IGNORE: no output or ...


2 Answers

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})
like image 119
maheeka Avatar answered Oct 07 '22 20:10

maheeka


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

like image 44
Niraj Sonawane Avatar answered Oct 07 '22 20:10

Niraj Sonawane