【Kotlin】日時型のLocalDateTimeをJSONに変換するだけで大変だった件

#はじめに
LocalDateTimeをJSON形式にしたかっただけなのに大変だったので覚え書きとして投稿します。

#準備
JSON形式を扱えるようにするGSONを使用します。

プロジェクトツリーからbuild.gradle(app)を開いて dependencies { のimplementationが並ぶ中に

```build.gradle(app)
implementation 'com.google.code.gson:gson:2.8.6'
```

を追加して右上に出てくる「Sync Now」または「今すぐ同期する」を選んで有効にします。

#使って見る

Gsonを使って日時型LocalDateTimeを内部データに持つクラスを作り、それをJson形式にしてみます。

```MainActivity.kt
open class gsonData(){
    var dStr : String = "test"
    var dInt : Int = 1234
    var dDouble : Double = 5.6
    @RequiresApi(Build.VERSION_CODES.O)
    var dTime : LocalDateTime = LocalDateTime.now()
}
class MainActivity : AppCompatActivity() {
    val gson = Gson()
    val gsonData = gsonData()

    @RequiresApi(Build.VERSION_CODES.O)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val str = gson.toJson(gsonData)
    }
}
```

結果は

```出力結果.txt
{"dDouble":5.6,"dInt":1234,"dStr":"test","dTime":{}}
```
LocalDateTimeが出力されてませんね。
GsonでLocalDateTimeをJSon形式で出力するにはGsonBuilderを使用してLocalDateTimeクラスをどのようにJsonへ変換するのかを指定しないと駄目なようです。

しかしGsonBuilderの使い方がさっぱりわかりません。
英語で書いてあるJavaでの説明を見て少し理解し、それをなんとかKotlinへ対応させました。

#ソース

```MainActivity.kt
open class gsonData(){
    var dStr : String = "test"
    var dInt : Int = 1234
    var dDouble : Double = 5.6
    @RequiresApi(Build.VERSION_CODES.O)
    var dTime : LocalDateTime = LocalDateTime.now()
}

internal class LocalDateTimeSerializer : JsonSerializer<LocalDateTime?> {
    @RequiresApi(Build.VERSION_CODES.O)
    override fun serialize(
        localDateTime: LocalDateTime?,
        srcType: Type?,
        context: JsonSerializationContext?
    ): JsonElement {
        return JsonPrimitive(formatter.format(localDateTime))
    }

    companion object {
        @RequiresApi(Build.VERSION_CODES.O)
        private val formatter: DateTimeFormatter =
            DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss.SSS")
    }
}

internal class LocalDateTimeDeserializer() : JsonDeserializer<LocalDateTime>, Parcelable {
    constructor(parcel: Parcel) : this() {
    }

    @RequiresApi(Build.VERSION_CODES.O)
    @Throws(JsonParseException::class)
    override fun deserialize(
        json: JsonElement,
        typeOfT: Type,
        context: JsonDeserializationContext
    ): LocalDateTime {
        return LocalDateTime.parse(
            json.asString,
            DateTimeFormatter.ofPattern("yyyy/MM/dd HH::mm:ss.SSS").withLocale(Locale.ENGLISH)
        )
    }

    override fun writeToParcel(parcel: Parcel, flags: Int) {}

    override fun describeContents(): Int {return 0 }

    companion object CREATOR : Parcelable.Creator<LocalDateTimeDeserializer> {
        override fun createFromParcel(parcel: Parcel): LocalDateTimeDeserializer {
            return LocalDateTimeDeserializer(parcel)
        }

        override fun newArray(size: Int): Array<LocalDateTimeDeserializer?> {
            return arrayOfNulls(size)
        }
    }
}

class MainActivity : AppCompatActivity() {
    val gsonData = gsonData()
    var gsonBuilder = GsonBuilder()

    @RequiresApi(Build.VERSION_CODES.O)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        gsonBuilder.registerTypeAdapter(gsonData.dTime.javaClass, LocalDateTimeSerializer())
        gsonBuilder.registerTypeAdapter(gsonData.dTime.javaClass, LocalDateTimeDeserializer())
        val gson = gsonBuilder.setPrettyPrinting().create()
        val str = gson.toJson(gsonData)
    }
}
```

出力結果

```出力結果.txt
{
      "dDouble": 5.6,
      "dInt": 1234,
      "dStr": "test",
      "dTime": "2021/03/17 18:30:51.543"
    }
```

#おわりに
Javaのクラス型を渡す方法がわからず苦労しました。
なんだか出力結果が変わったのですが　**とりあえず動いてるのでヨシ！！**　です。

使う場合は後で困らないように、しっかり動作確認してください。