2020/3/6追記
当初はこのライブラリの名前をMapKとしていましたが、MapKはオーガナイゼーションの名前として、ライブラリ名はKMapperに変更しました。
前書き
Kotlin向けModelMapper的なライブラリが欲しかったので作りました。
この記事では、KMapperの基本的な使い方についてまとめます。
バージョンは0.1時点での内容です。
ライブラリのソースコードはGitHubに公開してあります。
導入方法
JitPackにて公開しており、MavenやGradleといったビルドツールから利用できます。
詳しい導入方法は以下のリンクからご確認ください。
開発背景
Javaでは、POJOに対してオブジェクトからデータをマップできるModelMapperという便利なライブラリが有ります。
一方、このライブラリは当然ですがKotlinには対応していません。
Kotlinは基本的にコンストラクタで初期化を完了する一方、ModelMapperは「引数無しコンストラクタでインスタンス生成 -> セッターでデータをそれぞれマッピング」という手順での初期化を想定しているためです。
無理やりModelMapperを使ってKotlinのオブジェクトを初期化することも不可能ではありませんが、その場合immutabilityやNull安全が犠牲になったりと、Kotlinの良さが殺されてしまいます。
また、デフォルト引数に関しても利用することができません。
つまり、そういった機能を十全に使おうと思えばマッパーの利用をあきらめ手動で引数を調整して書くしか有りませんでした。
このため、srcからKotlinのコンストラクタやファクトリーメソッドを呼び出せるようなマッパーライブラリが欲しいと思いました。
なにができるか
以下のように、KMapperを用いることで、Dstクラスのコンストラクタをsrcのプロパティから呼び出すことができます。
// KMapperを使わない場合
val dst = Dst(
param1 = src.param1,
param2 = src.param2,
param3 = src.param3,
param4 = src.param4,
param5 = src.param5,
...
)
// KMapperを使う場合
val newInstance = KMapper(::Dst).map(src)
KMapperの引数
KMapperの引数は、基本的にはコンストラクタやファクトリメソッド、インスタンス関数を含むメソッドリファレンス(≒ KFunction<*>)です。
クラスを引数とすることで、プライマリコンストラクタ、もしくはKConstructorアノテーションを振ったコンストラクタ/ファクトリーメソッドを呼び出し対象とすることも可能です。
Javaへの対応に関して
基本的にJavaのクラス・関数には対応しません。
マッピングにはKotlinのメタデータを利用していることと、Javaでは引数の名前が取得できない場合があることが理由です。
srcに指定できる内容
マップ元には以下が指定できます。
Map<String, Any?>-
Kotlinクラスのインスタンス -
Kotlinクラスのインスタンス、Map<String, Any?>、Pair<String, Any?>から構成される可変長引数
Kotlinクラスのインスタンスからは、valやvarで定義されたプロパティ(KProperty)のみを抽出してマッピングを行います。
Javaへの対応に関して
前述の通り、valやvarで定義されたプロパティのみが対象であるため、Javaのゲッターからは抽出を行っておりません。
技術的には不可能ではありませんが、現状では敢えて対応するほどでもないと考えています。
終わりに
今回は自作のKotlin向けModelMapper的なライブラリ、KMapperに関して書きました。
引数間の変換機能なども有りますが、長くなるので個別の記事としてまとめようと思います。
ドキュメント・テスト等足りない部分は多々ありますが、こちらも今後対応していく予定です。
PR、質問等も募集中です。
是非使ってみて下さいm(_ _)m