DEV Community

kaede
kaede

Posted on

Kotlin Springboot -- Part 7 Rest でドメインのデータクラスから JSON のためのデータクラスに変換して JSON に変換する

why

前回は Driver で DB や API などから取ってこられる DB テーブルの世界のエンティティを返し、
Gateway でエンティティを業務の世界のオブジェクトを表すデータクラスである Domain に詰め直した。

今回は Usecase を介して渡された Domain オブジェクトを API として JSON で出力するための新しいデータクラスに Rest で変換する。

これは DomainName.toJson と名付け、Domain の拡張だが、Rest に定義する。

Django で Serializer が行っていた役割と似ているが、こちらは型をつける必要が有る。


REST のどこに書くのか

@RestController
class PersonHandler {
  @GetMapping("/persons")
  fun getPersons(): String {
  // .....
}
Enter fullscreen mode Exit fullscreen mode

この HTTP リクエストの対応を書くクラスの外に JSON のためのデータクラスを作る。


Json にするための ObjectJson のデータクラスを作る

data class PersonsJson(val persons: List<PersonJson>)
data class PersonJson(
  val name: String,
  val age: Int,
)
Enter fullscreen mode Exit fullscreen mode

JSON レスポンスのためのデータクラス。
JSON には型はないので、JSON にした瞬間に型は消滅し
val で入っている key と中身が残る。

{
  "persons": [
    {
      "name": "text",
      "age": 12345
    }
  ]
Enter fullscreen mode Exit fullscreen mode

よって、val persons とその中の配列の
val name, val age, これらがこうやって返される。


Domain から ObjectJson にするための Object.toJson 関数を作る

Domain のデータクラス、Persons を拡張する。
こちらも REST に書く。
toJson といいつつ、これを実行したところで JSON にはならない。
JSON に変換する事前準備のための型という意味。

fun Persons.toJson() = PersonsJson(this.list.map { (it.toJson())})

fun Person.toJson(): PersonJson {
  val personJson = PersonJson( this.name.value, this.age.value,)
  return personJson
}
Enter fullscreen mode Exit fullscreen mode

Person*s*.toJson では
ドメインの Persons を map して
中身の各 Person に Person.toJson を実行させる。

Persons.toJson では this で参照して
name と age の value を出して PersonJson の中にいれて return する。

Domain のデータクラスの中に入っていたものを
Json 用のデータクラスの中に詰め替えている。


Kotlin オブジェクトを JSON に変換するための gson ライブラリを入れる

bulid.grade.kts を開き

dependencies {
    //...
    implementation ("com.google.code.gson:gson:2.9.1")
}
Enter fullscreen mode Exit fullscreen mode

gson の依存を書いて Gradle をリロードする。
すると gson ライブラリがインストールされる。


REST で gson を呼び出す

import com.google.gson.Gson
// ...
  val persons = personsUsecase.getAllPersons()
  val gson = Gson()
  val personsJson = persons.toJson()
  val json2 = gson.toJson(personsJson)

Enter fullscreen mode Exit fullscreen mode

Gson はこのように使える。
UseCase などのインスタンスを作る時と同じように
一度クラスからインスタンスを作り、
そのインスタンスからメンバー関数を呼び出す。

Usecase から呼び出された Domain に入った persons を toJson 型に詰め直して、その後 gson で変換する。


web で確認する

Springbooot で起動したサーバーにアクセスすると
このようにレスポンスが綺麗にみえた。これで使える。

// 20220908225236
// http://localhost:8080/persons

{
  "persons": [
    {
      "name": "taro",
      "age": 3
    },
    {
      "name": "hana",
      "age": 5
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

まとめ

DB テーブルの都合のエンティティ
オブジェクト指向の都合のドメイン
JSON の都合のtoJson

これらの 3 つのデータクラスを使い分けるのが、クリーンアーキテクチャ。

Kotlin クリーンアーキテクチャで REST で API に適した JSON を返す。

そのためには Gateway でオブジェクト指向の都合で Domain に詰められているものを Usecase から Rest に運んできた後に

JSON 用のデータクラスに詰め替えて、その上で gson を使って JSON に変換すればうまく行く。

Domain のまま JSON に変換するとこうなりますからね。

{
  "list":[
    {
      "name":{
        "value":"taro"
      },
      "age":{
        "value":3
      }
    },
    {
      "name":{
        "value":"hana"
      },
      "age":{
        "value":5
      }
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)