Option to map multiple objects into one
mohsunb opened this issue · 5 comments
Hi.
Today I needed to combine class A and B into C using Konverter
. When having a method with A and B as parameters, compiler complains about multiple parameters. If I annotate either with Konverter.Source
, the other one is completely ignored as if it didn't even exist.
This was fairly easy with MapStruct
in Java, but I did not manage to replicate the same with Konvert
. Is this something planned or not?
With Konverter.Source
you can already pass additional parameters to a mapping function, which will automatically be recognized and used, see example below.
class SourceClass(val property: String)
class TargetClass(val property: String, val other: Int)
@Konverter
interface Mapper {
fun toTarget(@Konverter.Source source: SourceClass, other: Int): TargetClass
}
As far as I understand, you would like to have something like this:
class SourceClass(val property: String)
class OtherSourceClass(val other: Int)
class TargetClass(val property: String, val other: Int)
@Konverter
interface Mapper {
fun toTarget(source: SourceClass, otherSourceClass: OtherSourceClass): TargetClass
}
Currently this is not supported, but sounds like a legitimate feature request. There are definitely some challenges with that, but I will have a look.
Thanks for the answer! This actually helped me quite a lot. I will keep the issue open if you want to try implementing this feature. But no pressure. :)
Without understanding the exact use-case of @mohsunb I'd be weary of adding that feature to the library. What would be the expected behaviour if OtherSourceClass
would evolve into:
class OtherSourceClass(val property: String, val other: Int)
I think it would require quite a bit of additional configuration in the shape of annotations to make it work. Wouldn't it be easier and more robust to let the caller handle it?
mapper.toTarget(sourceClass, otherSourceClass.other)
Yes, that is one of the challenges I also thought of. For this, I have some ideas, but they all come with downsides:
- One could add validation, so when it is unclear for Konvert, it might simply break. Downside is, that this might create mistrust in Konvert (at least into that functionality). So it must be documented and the error message must be directly understandable.
- Add implicit or explicit "priority" to the function parameter. Implicit: The first has highest prio, the last lowest prio if multiple sources match a property. Explicit: Add annotation to parameters to let user decide prio. For the implicit way: this has to be documented VERY good, otherwise this is confusing as it is not intuitive and "black magic". The second one might be a bit too verbose. Both have the downside, that you can not interchange priority between fields of the sources.
- Add ability to Konvert to allow some kind of dot-separated property path (e.g.
@Mapping(source = "sourceName.fieldName", target = "targetField")
). This is probably the biggest change and might also bring some challenges in resolution of that property path. Downside is probably only the effort and complexity this adds to Konvert.
I am open to further suggestions and points I might have forgotten and/or should consider.
@stravag thanks for your PR with the added documentation and the unit test 👍 Appreciate that!
Hello.
One use case I often encounter at my job is to combine columns of two (or more) tables. As in, multiple JPA Entity classes into one DTO.
@stravag Regarding your concern of OtherSourceClass
evolving over time. With MapStruct
, if the source is ambiguous it would just break during compilation and ask for explicit source declaration. So, if the developer intends to change the OtherSourceClass
, they have to adjust to mapping accordingly. Which, I think, is totally fair.
@mcarleio I agree with your first and third ideas since they are present in MapStruct
as well and I am used to it, but that's just my opinion. The "black magic" you mentioned does not sound quite intuitive, I'd recommend against that.