検証環境
この記事の内容は、以下の環境で検証しました。
- Intellij IDEA ULTIMATE 2017.3
- Kotlin 1.2
- Java 1.8
- Moshi 1.5.0
- Gradle Projectで作成
目標
Moshiの利用方法を理解する。
具体的には以下を理解する。
- JSONをパースして、データクラスのオブジェクトを生成
- データクラスからJSONの生成
Moshiとは
Moshiとは、JavaやAndroid向けのモダンなJSONライブラリーです。
また、JSONからJavaのオブジェクトへの変換が簡単に行なえます。
準備
Moshiを使用するため、Gradleに以下の1行を追記します。
compile 'com.squareup.moshi:moshi-kotlin:1.5.0'
事前準備
本記事とは直接関係ないですが、サンプルで使用しているクラスを事前に説明しておきます。
Userデータクラス
JSONからオブジェクトやオブジェクトからJSONにパースする際に使用するクラスです。
data class User(val name:String,val detail:UserDetail)
UserDeatailデータクラス
Userクラスのプロパティとして保持するクラスです。
data class UserDetail(val age:Int, val job:String)
createUser関数
Userデータクラスで、サンプルデータを保持したオブジェクトを生成する関数です。
fun createUser():User{
return User("山田太郎",UserDetail(25,"会社員"));
}
createMultiUser関数
Userデータクラスのオブジェクトを格納したList型のオブジェクトを生成する関数です。
fun createMultiUser(): List<User> {
return listOf<User>(User("福沢諭吉",UserDetail(66,"偉人")),
User("樋口一葉",UserDetail(24,"作家")),
User("野口英世",UserDetail(51,"医師")))
}
実装例
クラス→JSON変換
コード例
オブジェクトをJSONに変換するコードは、以下のとおりです。
val user = createUser()
// クラス→JSON変換
val moshi = Moshi.Builder().build()
val adapter = moshi.adapter(User::class.java)
val decodeJson = adapter.toJson(user)
println("クラス→JSON:${decodeJson}")
解説
Moshiを使用するには、Moshiのオブジェクトが必要です。そのオブジェクトを生成するには、MoshiのBuilderクラスを使用し、builderメソッドを呼び出します。
val moshi = Moshi.Builder().build()
adapterメソッドで、変換するクラス情報をMoshiに渡します。
戻り値として、JsonAdapter型のオブジェクトが帰ってきます。
val adapter = moshi.adapter(User::class.java)
JsonAdapterクラスのtoJsonメソッドでJSONを生成します。
val decodeJson = adapter.toJson(user)
実行結果
クラス→JSON:{"detail":{"age":25,"job":"会社員"},"name":"山田太郎"}
JSON→クラス変換
コード例
JSONからオブジェクトに変換するコードは、以下のとおりです。
// JSON→クラス変換
val json = "{\"detail\":{\"age\":30,\"job\":\"自営業\"},\"name\":\"佐藤二朗\"}"
val fromJson = adapter.fromJson(json)
println("JSON→クラス:${fromJson}")
解説
パースするJSON文字列を準備しています。
val json = "{\"detail\":{\"age\":30,\"job\":\"自営業\"},\"name\":\"佐藤二朗\"}"
『クラス→JSON変換』で生成したJsonAdapterのfromJsonメソッドでパースします。
val fromJson = adapter.fromJson(json)
実行結果
実行結果は、以下の通りです。
JSON→クラス:User(name=佐藤二朗, detail=UserDetail(age=30, job=自営業))
リストに格納されたクラス→JSON
コード例
オブジェクトを格納したリストをJSONに変換するコードは、以下のとおりです。
val type = Types.newParameterizedType(List::class.java,User::class.java)
val listAdapter:JsonAdapter<List<User>> = moshi.adapter(type)
val multiUserJson = listAdapter.toJson(createMultiUser())
println("リストに格納されたクラス→JSON:${multiUserJson}")
解説
List型などのコレクション型をJSON文字列にする際、Types.newParameterizedTypeメソッドでParameterizedTypeクラスのオブジェクトを生成します。
Moshiのadapterメソッドの引数にParameterizedTypeクラスのオブジェクトを渡すことにより、List型のJsonAdapterが生成できます。
val type = Types.newParameterizedType(List::class.java,User::class.java)
val listAdapter:JsonAdapter<List<User>> = moshi.adapter(type)
JSON文字列の生成は、これまでのadapter同様にtoJsonメソッドを呼び出します。
val multiUserJson = listAdapter.toJson(createMultiUser())
実行結果
実行結果は、以下の通りです。
リストに格納されたクラス→JSON:[{"detail":{"age":66,"job":"偉人"},"name":"福沢諭吉"},{"detail":{"age":24,"job":"作家"},"name":"樋口一葉"},{"detail":{"age":51,"job":"医師"},"name":"野口英世"}]
JSON→リストに格納されたクラス
コード例
JSON文字列からオブジェクトを格納したリストに変換するコードは、以下のとおりです。
val file = File("src/main/resources/list_data.json")
val fileContents = file.absoluteFile.bufferedReader().use { it.readText() }
val listObject = listAdapter.fromJson(fileContents);
println("JSON→リストに格納されたクラス:${listObject}")
解説
サンプルデータはファイルで用意したため、ファイルの読み込みを記述しています。
val file = File("src/main/resources/list_data.json")
val fileContents = file.absoluteFile.bufferedReader().use { it.readText() }
ちなみに、今回使用するJSON文字列は以下の通りです。
[
{
"name": "佐藤一郎",
"detail": {
"age": 21,
"job": "コック"
}
},
{
"name": "山田花子",
"detail": {
"age": 35,
"job": "パティシエ"
}
},
{
"name": "木村二郎",
"detail": {
"age": 45,
"job": "経営者"
}
}
]
adapterの生成方法は、『JSON→リストに格納されたクラス』と同じです。
adapterのfromJsonを呼び出すことに、List型の値が取得できます。
val listObject = listAdapter.fromJson(fileContents);
実行結果
実行結果は、以下の通りです。
JSON→リストに格納されたクラス:[User(name=佐藤一郎, detail=UserDetail(age=21, job=コック)), User(name=山田花子, detail=UserDetail(age=35, job=パティシエ)), User(name=木村二郎, detail=UserDetail(age=45, job=経営者))]
まとめ
世の中には様々なJSONのライブラリーが存在します。多くのライブラリーは、パース処理やJSON文字列変換処理を静的メソッドで定義しており、Adapterを生成する必要がありません。使い慣れるまで時間は掛かりそうですが、様々なカスタマイズが可能です。
いつか使い倒したい。