Home About Contact
Kotlin , Kotlin Serialization , JSON , Gradle

Kotlin Serialization で JSON を扱う その3 Gradle プロジェクト

過去に Kotlin Script で Serialization を使うコードを書いた。 今回は普通に Gradle プロジェクトでそれを使うことにした。

バージョンの確認:

$ gradle --version
Gradle 8.12

$ java -version
openjdk version "17.0.6" 2023-01-17 LTS

gradle init してプロジェクトの雛形を作成:

$ gradle init

Select type of build to generate:
  1: Application
  2: Library
  3: Gradle plugin
  4: Basic (build structure only)
Enter selection (default: Application) [1..4] 1

Select implementation language:
  1: Java
  2: Kotlin
  3: Groovy
  4: Scala
  5: C++
  6: Swift
Enter selection (default: Java) [1..6] 2

Enter target Java version (min: 7, default: 21): 17

Project name (default: hello): 

Select application structure:
  1: Single application project
  2: Application and library project
Enter selection (default: Single application project) [1..2] 1

Select build script DSL:
  1: Kotlin
  2: Groovy
Enter selection (default: Kotlin) [1..2] 1

Select test framework:
  1: kotlin.test
  2: JUnit Jupiter
Enter selection (default: kotlin.test) [1..2] 1

Generate build using new APIs and behavior (some features may change in the next minor release)? (default: no) [yes, no] yes

不要なファイルを削除したり、ファイルを移動したりした結果:

$ tree .
.
├── app
│   ├── build.gradle.kts
│   └── src
│       ├── main
│       │   └── kotlin
│       │       └── App.kt
│       └── test
│           └── kotlin
│               └── AppTest.kt
├── gradle
│   ├── libs.versions.toml
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
└── settings.gradle.kts

App.kt, AppTest.kt を修正

app/src/main/kotlin/App.kt:

@file:Suppress("InvalidPackageDeclaration")
package org.example

import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json

@Serializable
data class Pokemon(val name: String, val hp: Int)

fun main() {
    val json = Json { prettyPrint = true }

    val pokemon = Pokemon("Pikachu", 100)
    val pokemonJsonString = json.encodeToString(pokemon)
    println( pokemonJsonString )

    val restoredPokemon = json.decodeFromString<Pokemon>(pokemonJsonString)
    println(restoredPokemon)
}

app/src/test/kotlin/AppTest.kt:

@file:Suppress("InvalidPackageDeclaration")
package org.example

import kotlin.test.Test
import kotlin.test.assertEquals

import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json

class AppTest {
    @Test fun test1() {
        val json = Json { prettyPrint = false }

        val pokemon = Pokemon("Pikachu", 100)
        val pokemonJson = json.encodeToString(pokemon)
        assertEquals( "{\"name\":\"Pikachu\",\"hp\":100}", pokemonJson )
    }
}

ビルド用の設定ファイルを修正

gradle/libs.versions.toml:

[versions]
kotlinx-serialization-json = "1.8.0"

[libraries]
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization-json" }

[plugins]
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version = "2.0.21" }
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version = "2.1.0" }

app/build.gradle.kts:

plugins {
    alias(libs.plugins.kotlin.jvm)
    alias(libs.plugins.kotlin.serialization)
    application
}

repositories {
    mavenCentral()
}

dependencies {
    implementation(libs.kotlinx.serialization.json)
}

testing {
    suites {
        val test by getting(JvmTestSuite::class) {
            useKotlinTest("2.0.21")
        }
    }
}

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(17)
    }
}

application {
    mainClass = "org.example.AppKt"
}

useKotlinTest("2.0.21") のバージョン部分を libs.versions.toml に記述するにはどうすればいいのだろうか。

ビルドして実行

$ ./gradlew run
> Task :app:run
{
    "name": "Pikachu",
    "hp": 100
}
Pokemon(name=Pikachu, hp=100)

テストを実行

$ ./gradlew test

追伸 gradle.properties でキャッシュをOFF に

gradle init で生成される gradle.properties はキャッシュが true になっている。

org.gradle.configuration-cache=true
org.gradle.parallel=true
org.gradle.caching=true

意外にこれでハマるので少なくとも最初はキャッシュをオフにしておいた方がいいかもしれない。 このように:

org.gradle.configuration-cache=false
org.gradle.parallel=true
org.gradle.caching=false

以上です。