AMR
AMR

Reputation: 146

MapStruct in Kotlin: How to map from multiple sources into one model?

Let's say I have model:

data class MyModel(
    var firstName: String,
    var lastName: String,
)

And let's say I'm attempting to map some properties into this model from my source PersonInfo

public final data class PersonInfo(
    val firstName: String,
    val lastName: String,
)

This is easy enough; I just run

fun persontoToModel(personInfo: PersonInfo): MyModel

Now let's say MyModal is now:

data class MyModel(
    var firstName: String,
    var lastName: String,
    var dateOfBirth: String,
    var licenseNumber: String,
)

Let's also say not all of this information is available in PersonInfo. Instead, dateOfBirth is available in PersonDetails, and licenseNumber is available in PersonDocuments, both of which also include a bunch of other properties that I don't necessarily need to map in this case.

PersonDetails and PersonDocuments:

public final data class PersonDetails(
    val dateOfBirth: LocalDate,
    val weight: String,
    val height: String,
    val eyeColor: String,
)

public final data class PersonDocuments(
    val licenseNumber: String,
    val passportNumber: String,
    val socialSecurityNumber: String,
)

From my understanding from the documentation, I can manually map these fields by specifying them with the source in a Mapping annotation as follows:

@Mapping(source="personDetails.dateOfBirth", target="dateOfBirth")
@Mapping(source="personDocuments.licenseNumber", target="licenseNumber")
@BeanMapping(ignoreUnmappedSourceProperties = [ all the other stuff I don't need])
fun persontoToModel(personInfo: PersonInfo, personDetails: PersonDetails, personDocuments: PersonDocuments): MyModel

Except this doesn't work. First and foremost, the second mapping annotation is highlighted as error with the reason "This annotation is not repeatable." I'm not sure if it's a Kotlin thing, since the documentations on MapStruct seem to only use Java examples.

Upvotes: 2

Views: 2919

Answers (1)

Georgian
Georgian

Reputation: 8960

@Mappings(
  Mapping(source="personDetails.dateOfBirth", target="dateOfBirth"),
  Mapping(source="personDocuments.licenseNumber", target="licenseNumber")
)
@BeanMapping(ignoreUnmappedSourceProperties = [ all the other stuff I don't need])
fun persontoToModel(personInfo: PersonInfo, personDetails: PersonDetails, personDocuments: PersonDocuments): MyModel

As of Kotlin 1.1, repeated annotations are not supported (see KT-12794). You have to wrap the Mapping-Annotation in a Mappings-Annotation.

Source

Upvotes: 2

Related Questions