KtorでContentNegotiationがみつからずにエラーになる【Kotlinサーバーサイドプログラミング実践開発】

# はじめに

以下の書籍を読んでいてKtorのライブラリについてつまづいたのでまとめます

https://www.amazon.co.jp/Kotlin-%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E3%82%B5%E3%82%A4%E3%83%89%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E5%AE%9F%E8%B7%B5%E9%96%8B%E7%99%BA-%E7%AB%B9%E7%AB%AF-%E5%B0%9A%E4%BA%BA/dp/4297118599/ref=sr_1_5?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=QCJAHQ0UNYFV&keywords=kotlin&qid=1673324056&sprefix=kotli%2Caps%2C203&sr=8-5

# 問題

書籍P259の「Jacksonのフィーチャーを追加」のところで`ContetnNegotiation`がみつからずコンパイルエラーとなっていました

書籍のリポジトリを確認したところ

```
import io.ktor.features.ContentNegotiation
```

こちらで入れていましたが、ktorにfeaturesというのはありませんでした

# 試行錯誤

まずは以下の依存を追加してみました

```
implementation("ktor-client-features:1.6.8")
```

しかし、ContentNegotiationはありませんでした

次に[こちらのリポジトリ](https://github.com/mizumura3/ktor-test-sample/blob/master/src/test/kotlin/com/example/ApplicationTest.kt)を参考に以下を追加してみました

```
implementation("ktor-client-plugins:1.6.8")
```

しかしこれもうまくいきませんでした

# 解決方法

最終的に以下のコードにすることで解決しました

```kotlin:build.gradle.kt
val ktor_version: String by project
val kotlin_version: String by project
val logback_version: String by project

plugins {
    kotlin("jvm") version "1.8.0"
    id("io.ktor.plugin") version "2.2.1"
                id("org.jetbrains.kotlin.plugin.serialization") version "1.8.0"
}

group = "com.example"
version = "0.0.1"
application {
    mainClass.set("com.example.ApplicationKt")

    val isDevelopment: Boolean = project.ext.has("development")
    applicationDefaultJvmArgs = listOf("-Dio.ktor.development=$isDevelopment")
}

repositories {
    mavenCentral()
}

dependencies {
    implementation("io.ktor:ktor-server-core-jvm:$ktor_version")
    implementation("io.ktor:ktor-server-resources:$ktor_version")
    implementation("io.ktor:ktor-server-netty-jvm:$ktor_version")
    implementation("ch.qos.logback:logback-classic:$logback_version")
    implementation("io.ktor:ktor-server-content-negotiation:$ktor_version") // 追加
    implementation("io.ktor:ktor-serialization-kotlinx-json:$ktor_version") // 追加
    implementation("io.ktor:ktor-jackson:1.6.8")
    testImplementation("io.ktor:ktor-server-tests-jvm:$ktor_version")
    testImplementation("org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version")
}
```

```kotlin:Application.kt
package com.example

import io.ktor.server.application.*
import io.ktor.server.engine.*
import io.ktor.server.netty.*
import io.ktor.server.routing.*
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.serialization.kotlinx.json.*
import io.ktor.server.resources.*

fun main() {
    embeddedServer(Netty, port = 8080, host = "0.0.0.0", module = Application::module)
        .start(wait = true)
}

fun Application.module() {
    install(Resources)
    install(ContentNegotiation) {
        json()
    }
    routing {
        bookRoute()
    }
}
```

```kotlin:BookRoute.kt
package com.example

import io.ktor.resources.*
import io.ktor.server.application.*
import io.ktor.server.resources.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import kotlinx.serialization.Serializable

fun Routing.bookRoute() {

    get<BookLocation.GetBook> { request ->
        val response = BookResponse(request.bookId, "Kotlin入門", "Kotlin太郎")
        call.respond(response)
    }
}

@Serializable
@Resource("/book")
class BookLocation(){
    @Serializable
    @Resource("/detail/{bookId}")
    class GetBook(val parent: BookLocation = BookLocation(), val bookId: Long)
}
@Serializable
data class BookResponse(
    val id: Long,
    val title: String,
    val author: String,
)
```

そもそも`jackson`を使わなくてもktorの`io.ktor:ktor-server-content-negotiation`と`io.ktor:ktor-serialization-kotlinx-json`を使うことで同じようなことができるようになっていました

https://ktor.io/docs/serialization.html

# おわりに

やはり公式ドキュメントが一番ということを何度も最近感じさせられます
Kotlinはライブラリ関係のエラーがすごく多発して大変です

# 参考

https://tech.uzabase.com/entry/2020/03/17/090000

https://github.com/mizumura3/ktor-test-sample/blob/master/src/test/kotlin/com/example/ApplicationTest.kt

https://ktor.io/docs/serialization.html