I often see stories such as ModelMapper
that" a mapping library using reflection for Java
does not work for data class
of Kotlin
", so why is that so and to deal with it? Write what kind of means you have.
TL;DR
--The mapping library for Java
presupposes the procedure" Instantiate with no argument constructor-> Initialize individual fields "
--On the other hand, data class
of Kotlin
basically has no argument-less constructor.
--For this reason, the mapping library using reflection for Java
does not work for data class
of Kotlin
.
In this article, we use the term mapping library to mean:
--Mapping library: A library that provides the ability to create an object instance with fields initialized from some source.
ModelMapper
, BeanPropertyRowMapper
Also, the map destination on Kotlin
does not matter whether it is class
or data class
, but it will be data class
in many cases, so data class
is assumed in this article. Treat as.
--Try decompiling
--Move even if you force it
--About tools that support Kotlin
To confirm that " data class
does not have a no-argument constructor ", try decompiling the following class with the function of ʻidea`.
data class Sample(val foo: Int, val bar: Int?)
The result is as follows. You can see that there is no definition of a no-argument constructor.
Decompiled result (* Parts not related to the content of the article have been omitted)
/*Abbreviation*/
public final class Sample {
private final int foo;
@Nullable
private final Integer bar;
public final int getFoo() {
return this.foo;
}
@Nullable
public final Integer getBar() {
return this.bar;
}
public Sample(int foo, @Nullable Integer bar) {
this.foo = foo;
this.bar = bar;
}
/*Abbreviation*/
As explained so far, the reflection-based mapping library for Java
does not work for data class
in Kotlin
.
However, there are several ways to force it.
The Kotlin
formula provides a plugin that adds an argumentless constructor that can only be called at runtime.
By using this, the null
safety is broken, but the traditional library seems to work.
If you write the mapped class to work like a Java`` POJO
, the traditional library will work.
Also, if you separate the interface that exposes to the outside and the implementation of the class that stores the actual data, you can realize the situation that "looks like a normal data class
from the outside ".
If you want to give up the complete Kotlin
conversion, you can implement it with POJO
and then annotate the getter with Nullability
.
Finally, as far as I know, I will write about the ʻObject to Object mapping library that supports
Kotlin`.
KMapper
This is a function call-based mapping library created by the author by reflecting Kotlin
.
In addition to ʻObject, you can take
Map` etc. as an argument or perform mapping from multiple arguments.
Function calls by reflection of Kotlin
can be implemented relatively easily, so I feel that it is easy to make your own quickly if you do not want functionality.
MapStruct
Although it is in beta at the time of writing, MapStruct
seems to support mapping by calling the constructor from 1.4
.
As a supplement, I will omit the details, but I think that if it is a library based on ʻannotation-processor, it is easy to support
Kotlineven if it is for
Java`.
Jackson
Since Jackson
has Kotlin
support, this allows mapping to be achieved with the procedure "1 time JSON
-> deserialize".
It has a lot of features and can handle various sources as long as it can be serialized, so it may be surprisingly good to use Jackson
except for execution speed.
Recommended Posts