LoginSignup
8

More than 5 years have passed since last update.

posted at

FuelとMoshiの連携

検証環境

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

  • 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=医師))

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
What you can do with signing up
8