LoginSignup
11
8

More than 5 years have passed since last update.

FuelとMoshiの連携

Posted at

検証環境

この記事の内容は、以下の環境で検証しました。

  • Intellij IDEA ULTIMATE 2017.2
  • Kotlin 1.1.61
  • Fuel 1.12.0
  • Moshi 1.5.0
  • Java 1.8
  • Gradle Projectで作成

目標

Fuelには、JSONライブラリーと連携する機能が備わっています。
本記事は、『FuelとMoshiの連携方法を理解する』を目標とします。

【連携可能なライブラリー】
* GSON
* Moshi
* Jackson

前提

下記の記事を理解していることを前提として、本記事を記述しています。

事前準備

本記事とは直接関係ないですが、サンプルで使用しているクラスを事前に説明しておきます。

Userデータクラス

JSONからオブジェクトやオブジェクトからJSONにパースする際に使用するクラスです。

data class User(val name:String,val detail:UserDetail)

UserDeatailデータクラス

Userクラスのプロパティとして保持するクラスです。

data class UserDetail(val age:Int, val job:String)

返ってくるJSON

今回サンプル用にローカルに用意したサーバで返すJSONは以下の通りです。

単一オブジェクトのJSON

URL
http://localhost:8080/userInfo
JSON

{"detail":{"age":25,"job":"会社員"},"name":"山田太郎"}

配列形式のJSON

URL
http://localhost:8080/multiUserInfo

[{"detail":{"age":66,"job":"偉人"},"name":"福沢諭吉"},{"detail":{"age":24,"job":"作家"},"name":"樋口一葉"},{"detail":{"age":51,"job":"医師"},"name":"野口英世"}]

実装例

単一オブジェクトのJSON

コード例

レスポンスのJSONをデータクラスに変換するコードは、以下の通りです。

    "http://localhost:8080/userInfo".httpGet().responseObject<User> { req, res, result ->
        val(user,err) = result
        println("user:${user}");
    }

解説

レスポンスで受け取ったデータを指定したデータクラスの型に変換するには、『responseObject関数』を使用します。
関数のジェネリクスにデータクラスのを指定するだけで変換します。

responseObject<User>

resultにUserデータクラスに変換したオブジェクトが格納されています。
今回は分解宣言で取得しています。userという変数にUserデータクラスのオブジェクトが格納されます。

val(user,err) = result

実行結果

user:User(name=山田太郎, detail=UserDetail(age=25, job=会社員))

配列形式のJSON

コード例

配列形式のJSONをUserデータクラスを格納したリストに変換するコードは、以下の通りです。

JSONをList型に変換する処理を記述したクラス

package jp.co.casareal.fuelmoshi

import com.github.kittinunf.fuel.core.ResponseDeserializable
import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.Moshi
import com.squareup.moshi.Types

class UserListDeserializer : ResponseDeserializable<List<User>> {

    override fun deserialize(content: String): List<User>? {
        val moshi = Moshi.Builder().build()
        val type = Types.newParameterizedType(List::class.java, User::class.java)
        val listAdapter: JsonAdapter<List<User>> = moshi.adapter(type)

        return listAdapter.fromJson(content)
    }
}

HTTP通信を行い、レスポンスをUserListDeserializerでList型に変換する処理

    "http://localhost:8080/multiUserInfo".httpGet().responseObject(UserListDeserializer()) { req, res, result ->
        val(list,err) = result

        list?.forEach {
            println(it)
        }
    }

解説

配列のJSONを受け取る場合は、responseObject関数のジェネリクスで指定しても、List型に正しく変換されません。
変換するには、ResponseDeserializableを継承し、deserializeメソッドとオーバライドしたクラスを用意する必要があります。

class UserListDeserializer : ResponseDeserializable<List<User>> {
    override fun deserialize(content: String): List<User>? {
         ・・・省略・・・
    }
}

deserializeメソッド内でJSONからオブジェクトに変換する処理を行います。
処理内容詳細は、下記の記事に記述しています。
https://casareal-ls.qiita.com/naoi/items/64413e2777210526aa87

val moshi = Moshi.Builder().build()
val type = Types.newParameterizedType(List::class.java, User::class.java)
val listAdapter: JsonAdapter<List<User>> = moshi.adapter(type)

return listAdapter.fromJson(content)

deserializeメソッドはオーバロードされており、引数の型を以下から選べます。
* public fun deserialize(bytes: ByteArray): T?
* public fun deserialize(inputStream: InputStream): T?
* public fun deserialize(reader: Reader): T?
* public fun deserialize(content: String): T?

HTTP通信は単一オブジェクトのJSONと同じようにresponseObject関数を利用します。
responseObject関数の引数にUserListDeserializerクラスのインスタンスを渡すことによって
作成したUserListDeserializerクラスのdeserializeメソッドが動作し、変換処理が行われます。

responseObject(UserListDeserializer()) 

以降は単一オブジェクトのJSONと同じ為、説明は省略します。

実行結果

User(name=福沢諭吉, detail=UserDetail(age=66, job=偉人))
User(name=樋口一葉, detail=UserDetail(age=24, job=作家))
User(name=野口英世, detail=UserDetail(age=51, job=医師))
11
8
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
8