[Kotlin] The mapping library by reflection based on Java basically does not work with Kotlin.

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.

Supplement

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.

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.

Text

--Try decompiling --Move even if you force it --About tools that support Kotlin

Try to decompile

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*/

Move even by force

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.

Use No-arg compiler plugin

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.

Write a no-argument constructor on Kotlin

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.

-[Kotlin] Not Null \ (NonNull ) / Nullable annotation handles Java fields from Kotlin safely [Java] -Qiita

About the library corresponding to Kotlin

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.

Make your own

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 forJava`.

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

[Kotlin] The mapping library by reflection based on Java basically does not work with Kotlin.
Correspondence when Java application exed by launch4j does not work on windows with openJDK installed
Java Integer comparison (==) does not work correctly
[For beginners] When you want to say that the JVM (-D) option does not work with the java -jar command, or that the library is buggy.
Does the escape sequence (\) not work? (for Mac)
Does not recognize the library when implementing jcaptcha
What to do if the JSONHint annotation does not work with lombok and JSONIC
Use fast Mapping library MapStruct with Lombok and Java 11
Note: Memory Analyzer does not work on Mac OS
When the server does not start with rails s
A memo when the incoming number acquisition using Broadcast Receiver does not work on Android 9/10