3

I would like to use mapstruct to map between these objects:

MyObj1
-List<MyObj2> myObj2List
--List<MyObj3> myObj3List
---string field1

MyObj4
-List<MyObj5> myObj5List
--List<MyObj6> myObj6List
---int field1

Question: can i somehow tell mapstruct to map the field1 from string to int OTHERWISE than the default Integer.parseInt(...)?

Changing the types of the inner objects is not an option. I know there is an annotaion

 @Mapping(source = "myObj2List.myObj3List.field1", target = "myObj5List.myObj6List.field1", qualifiedByName = "methodToMapWith")
 public MyObj4 field1Mapper(MyObj1input);
    
 @Named("methodToMapWith") 
 public static int methodToMapWith(string input) { 
    return ...[custom logic]...; 
 }

but since these are nested objects, this way i get an error saying No property named "myObj2List.myObj3List.field1" exists in source parameter(s). I must be formulating the source wrong. Any help please?

KGBR
  • 435
  • 1
  • 8
  • 17
  • Shouldn't that be `(source = "myInnerObj1.field1", target ="myInnerObj2.field1", qualifiedByName....)`? – Procrastinator Nov 02 '20 at 15:49
  • I updated the object structure to better reflect the real version. – KGBR Nov 02 '20 at 16:09
  • Still it is not a real version of your problem unless you are naming all wrong. What are these ```fieldNameInSource```, ```fieldnameInTarget``` names mean and why they do not correspond to any field name in your classes declarations? – Marcin Rzepecki Nov 02 '20 at 16:19
  • I have further edited, made it more clear. Thank you for the help! – KGBR Nov 02 '20 at 16:36

1 Answers1

1

You are trying to define mapping on collections. This is not supported by MapStruct.

When using

@Mapping(source = "myObj2List.myObj3List.field1", target = "myObj5List.myObj6List.field1", qualifiedByName = "methodToMapWith")

You are actually telling MapStruct that you want the property myObj3List from the myObj2List to be used. However, myObject2List is not a bean, but a collection.

You actually mean to tell MapStruct to pass the mapping to the created iterable mapping for the single elements.

I think that there is a feature request to support something like that.

In order to support what you need you'll need to add mapping methods between the different object.

e.g.

 @Mapping(source = "myObj2List", target = "myObj5List")
 public MyObj4 field1Mapper(MyObj1 input);

 @Mapping(source = "myObj3List", target = "myObj6List")
 public MyObj5 map(MyObj2 input);

 @Mapping(target = "field1", qualifiedByName = "methodToMapWith")
 public MyObj6 map(MyObj3 input);
    
 @Named("methodToMapWith") 
 public static int methodToMapWith(string input) { 
    return ...[custom logic]...; 
 }

When target and source are identical you don't have to define them, you can just define target and qualifiedByName

Filip
  • 19,269
  • 7
  • 51
  • 60