0

I have source and target classes that look like this

class UserHistorySource {
   private DetailsSource details;
}

and

class DetailsSource {

   private List<BalanceSource> balance;
   private List<RewardsSource> rewards;
   private List<LogsSource> logs;
   ….
   ….
}


class BalanceSource {

private String userId;
private OffsetDateTime datetime;
private String amount;

}


class RewardsSource {

private String userId;
private OffsetDateTime datetime;
private String amount;

}

class LogsSource {

private String userId;
private OffsetDateTime datetime;
private String amount;

}

Target Classes:

class UserHistoryTarget {
  private DetailsTarget details;
}

class DetailsTarget {

  private List<BalanceTarget> balance;
  private List<RewardsTarget> rewards;
  private List<LogsTarget> logs;
  ….
  ….
}


class BalanceTarget {

  private String userId;
  private String datetime;
  private String amount;
}


class RewardsTarget {
  private String userId;
  private String datetime;
  private String amount;
}

class LogsTarget {

  private String userId;
  private String datetime;
  private String amount;
}

The datetime in target classes are of type string while in source are of OffsetDateTime. I could potentially create indivisual mapper files for Details, Balance, Rewards and Logs and implement a default method to convert the OffsetDateTime to String but I want to avoid writting mapper files for each class, is there a better way to do this ?

1 Answer 1

2

You don't need to create mappers (or even: mapping methods) for all those classes.

It is sufficient (if you have getters and setters for the fields) to have have the following mapper definition:

@Mapper
interface UserHistoryMapper {
    UserHistoryTarget map(UserHistorySource source);

    default String map(OffsetDateTime odt) {
        // sample implementation
        return odt.toString();
    }
}

The MapStruct annotation processor will generate the needed mapping methods and call the String map(OffsetDateTime odt) where needed.

5
  • hey @thomas-kläger would you mind sharing some insights on what does map method do here ? Is map some sort of keyword in mapstruct ?
    – user641887
    Commented Jun 18 at 6:31
  • @user641887 not sure what you mean with what does map method do here. For the UserHistoryTarget map(UserHistorySource source) method the MapStruct annotation processor will generate the code that converts a UserHistorySource into a UserHistoryTarget (and initializes the fields of the UserHistoryTarget with converted values from the UserHistorySource). To do this the MapStruct annotation processor will generate methods to convert DetailsSource to DetailsTarget, BalanceSource to BalanceTarget and so on. Commented Jun 18 at 6:37
  • And the default String map(OffsetDateTime odt) method is my cheap way of converting from an OffsetDateTime to a String (because that is the only conversion that the MapStruct annotation processor does not generate). Commented Jun 18 at 6:39
  • thanks, I was using named annotation for this, so it looks like if we have multiple mappings like OffsetDatetime to string or Currency to String, we can have overloaded map methods to accomplish our needs instead of named annotation, correct ?
    – user641887
    Commented Jun 18 at 6:41
  • 1
    @user641887 yes, if MapStruct can determine the mapping method to use by source class and target class alone you don't need any qualifier. The MapStruct manual has an example where there are multiple possible mappings from one String to another String (mapstruct.org/documentation/1.5/reference/html/…) and in that case you must help MapStruct in selecting which method to use. If the mappings are distinct (from Currency to String vs. from OffsetDateTime to String) MapStruct can do this for you. Commented Jun 18 at 6:55

Not the answer you're looking for? Browse other questions tagged or ask your own question.