「Gson is deprecated.」らしいのでMoshiを試してみる

# はじめに
今までJSONパーサに[Gson](https://github.com/google/gson)を使っていたのですが、あの[JakeWharton](https://github.com/JakeWharton)氏曰く[「Gson is deprecated.」](https://www.reddit.com/r/androiddev/comments/ejjroe/kotlinx_json_vs_gson_a_short_article_about_kotlin/fcz3v0d/?utm_source=share&utm_medium=web2x)との事だったので、[Moshi](https://github.com/square/moshi)を試してみました。

[Moshi](https://github.com/square/moshi)はSquare社が開発した軽量なJSONパーサで、[Gson](https://github.com/google/gson)の不満点を解消するために作られたそうです。

軽くGsonとの比較も行います。
# 導入
```groovy:build.gradle
apply plugin: 'kotlin-kapt'
...

// Moshi
implementation 'com.squareup.moshi:moshi:1.9.2'
implementation 'com.squareup.moshi:moshi-kotlin:1.9.2'
kapt 'com.squareup.moshi:moshi-kotlin-codegen:1.9.2' // 1.9.Xからこれが無いと "Cannot serialize Kotlin type" エラーが発生する

// Retrofit
implementation "com.squareup.retrofit2:retrofit:2.7.0"
implementation "com.squareup.retrofit2:converter-moshi:2.7.0"
```

# シリアライズ
## Gson
```kotlin
data class Repos(
    val id: Int,
    val name: String,
    // 変数名とJSONキーが一致しない場合は@SerializedNameアノテーションを付ける
    @SerializedName("full_name") val fullName: String
)
```

## Moshi
```kotlin
@JsonClass(generateAdapter = true) // Adapter化に必要
data class Repos(
    val id: Int,
    val name: String,
    // 変数名とJSONキーが一致しない場合は@Jsonアノテーションを付ける
    @Json(name = "full_name") val fullName: String
)
```

# fromJSON
## Gson
```kotlin
    val jsonString = """
            {
                "id":1,
                "name":"name",
                "full_name":"fullName"
            }
        """.trimIndent()
    val gson = Gson()
    val repos = gson.fromJson(jsonString, Repos::class.java)
```

## Moshi

```kotlin
    val jsonString = """
            {
                "id":1,
                "name":"name",
                "full_name":"fullName"
            }
        """.trimIndent()
    val adapter = Moshi.Builder().build().adapter(Repos::class.java)
    val repos = adapter.fromJson(jsonText)
```

# toJSON
## Gson
```kotlin
    val gson = Gson()
    val repos = Repos(1, "name", "fullName")
    val jsonString = gson.toJson(repos)
```

## Moshi

```kotlin
    val adapter = Moshi.Builder().build().adapter(Repos::class.java)
    val repos = Repos(1, "name", "fullName")
    val jsonString = adapter.toJson(repos)
```

# Retrofitとの連携
## Gson
```kotlin
    private val gson = GsonBuilder()
        .setLenient()
        .create()
    return Retrofit.Builder()
        .baseUrl("https://api.github.com/")
        .addConverterFactory(GsonConverterFactory.create(gson))
        .build()
```

## Moshi
```kotlin
    private val moshi = Moshi.Builder()
        .add(KotlinJsonAdapterFactory())
        .build()
    return Retrofit.Builder()
        .baseUrl("https://api.github.com/")
        .addConverterFactory(MoshiConverterFactory.create(moshi))
        .build()
```

パッと見ではGsonの方がコード量が少なく見えますが、Gsonは[non-nullな変数にnullを入れてしまう可能性がある](https://qiita.com/egugue/items/f1f35c250f7a25768751)という問題点があるようで、kotlinのnull安全を正しく利用しようとするならMoshiを使った方が安全なようです。

# おわりに
今回の記事を書くにあたって以下のリンクを参考にさせて頂きました。
[【Qiita】Kotlinと相性が良いMoshiのkotlin extensionを使う](https://qiita.com/egugue/items/f1f35c250f7a25768751)
[【Qiita】Kotlin JSON (Moshi) 使い方](https://qiita.com/unpi/items/962a3d5ddf1ba9714fb2)