Ktor Server におけるコンテンツ・ネゴシエーションとシリアライズ
必要な依存関係: io.ktor:ktor-server-content-negotiation
コード例: json-kotlinx
ContentNegotiation プラグインは、主に2つの目的を果たします。
- クライアントとサーバー間でのメディアタイプのネゴシエーション。これには
AcceptおよびContent-Typeヘッダーを使用します。 - 特定のフォーマットでのコンテンツのシリアライズ/デシリアライズ。Ktor は、JSON、XML、CBOR、ProtoBuf の各フォーマットを標準でサポートしています。
クライアント側では、Ktor はコンテンツのシリアライズ/デシリアライズのために ContentNegotiation プラグインを提供しています。
依存関係の追加
ContentNegotiation
ContentNegotiation を使用するには、ビルドスクリプトに ktor-server-content-negotiation アーティファクトを含める必要があります。
特定のフォーマットのシリアライザーには追加のアーティファクトが必要であることに注意してください。たとえば、kotlinx.serialization で JSON を使用するには ktor-serialization-kotlinx-json 依存関係が必要です。
シリアライズ
kotlinx.serialization コンバーターを使用する前に、Setup セクションの説明に従って Kotlin serialization プラグインを追加する必要があります。
JSON
JSON データをシリアライズ/デシリアライズするには、kotlinx.serialization、Gson、Jackson のいずれかのライブラリを選択できます。
ビルドスクリプトに ktor-serialization-kotlinx-json アーティファクトを追加します。
ビルドスクリプトに ktor-serialization-gson アーティファクトを追加します。
ビルドスクリプトに ktor-serialization-jackson アーティファクトを追加します。
XML
XML をシリアライズ/デシリアライズするには、ビルドスクリプトに ktor-serialization-kotlinx-xml を追加します。
XML シリアライズは
jsNodeターゲットではサポートされていない ことに注意してください。
CBOR
CBOR をシリアライズ/デシリアライズするには、ビルドスクリプトに ktor-serialization-kotlinx-cbor を追加します。
ProtoBuf
ProtoBuf をシリアライズ/デシリアライズするには、ビルドスクリプトに ktor-serialization-kotlinx-protobuf を追加します。
ContentNegotiation のインストール
ContentNegotiation プラグインをアプリケーションに インストール するには、 指定された
install 関数に渡します。 以下のコードスニペットは、ContentNegotiation のインストール方法を示しています ... - ...
embeddedServer関数の呼び出し内。 - ...
Applicationクラスの拡張関数である明示的に定義されたmodule内。
シリアライザーの設定
Ktor は、JSON、XML、CBOR の各フォーマットを標準でサポートしています。また、独自のカスタムシリアライザーを実装することもできます。
JSON シリアライザー
アプリケーションに JSON シリアライザーを登録するには、json メソッドを呼び出します。
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.serialization.kotlinx.json.*
install(ContentNegotiation) {
json()
}json メソッドでは、JsonBuilder によって提供されるシリアライズ設定を調整することもできます。例:
install(ContentNegotiation) {
json(Json {
prettyPrint = true
isLenient = true
})アプリケーションに Gson シリアライザーを登録するには、gson メソッドを呼び出します。
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.serialization.gson.*
install(ContentNegotiation) {
gson()
}gson メソッドでは、GsonBuilder によって提供されるシリアライズ設定を調整することもできます。例:
install(ContentNegotiation) {
gson {
registerTypeAdapter(LocalDate::class.java, LocalDateAdapter())
setDateFormat(DateFormat.LONG, DateFormat.SHORT)
setPrettyPrinting()
}アプリケーションに Jackson シリアライザーを登録するには、jackson メソッドを呼び出します。
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.serialization.jackson.*
install(ContentNegotiation) {
jackson()
}jackson メソッドでは、ObjectMapper によって提供されるシリアライズ設定を調整することもできます。例:
install(ContentNegotiation) {
jackson {
configure(SerializationFeature.INDENT_OUTPUT, true)
setDefaultPrettyPrinter(DefaultPrettyPrinter().apply {
indentArraysWith(DefaultPrettyPrinter.FixedSpaceIndenter.instance)
indentObjectsWith(DefaultIndenter(" ", "
"))
})
registerModule(JavaTimeModule()) // java.time.* 型をサポート
}
}XML シリアライザー
アプリケーションに XML シリアライザーを登録するには、xml メソッドを呼び出します。
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.serialization.kotlinx.xml.*
install(ContentNegotiation) {
xml()
}xml メソッドでは、XML シリアライズ設定にアクセスすることもできます。例:
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.serialization.kotlinx.xml.*
import nl.adaptivity.xmlutil.*
import nl.adaptivity.xmlutil.serialization.*
install(ContentNegotiation) {
xml(format = XML {
xmlDeclMode = XmlDeclMode.Charset
})
}CBOR シリアライザー
アプリケーションに CBOR シリアライザーを登録するには、cbor メソッドを呼び出します。
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.serialization.kotlinx.cbor.*
install(ContentNegotiation) {
cbor()
}cbor メソッドでは、CborBuilder によって提供される CBOR シリアライズ設定にアクセスすることもできます。例:
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.serialization.kotlinx.cbor.*
import kotlinx.serialization.cbor.*
install(ContentNegotiation) {
cbor(Cbor {
ignoreUnknownKeys = true
})
}ProtoBuf シリアライザー
アプリケーションに ProtoBuf シリアライザーを登録するには、protobuf メソッドを呼び出します。
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.serialization.kotlinx.protobuf.*
install(ContentNegotiation) {
protobuf()
}protobuf メソッドでは、ProtoBufBuilder によって提供される ProtoBuf シリアライズ設定にアクセスすることもできます。例:
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.serialization.kotlinx.protobuf.*
import kotlinx.serialization.protobuf.*
install(ContentNegotiation) {
protobuf(ProtoBuf {
encodeDefaults = true
})
}カスタムシリアライザー
指定した Content-Type に対してカスタムシリアライザーを登録するには、register メソッドを呼び出す必要があります。以下の例では、application/json および application/xml データをデシリアライズするために 2 つの カスタムシリアライザー が登録されています。
install(ContentNegotiation) {
register(ContentType.Application.Json, CustomJsonConverter())
register(ContentType.Application.Xml, CustomXmlConverter())
}データの受信と送信
データクラスの作成
受信したデータをオブジェクトにデシリアライズするには、データクラスを作成する必要があります。例:
data class Customer(val id: Int, val firstName: String, val lastName: String)kotlinx.serialization を使用する場合は、このクラスに @Serializable アノテーションが付いていることを確認してください。
import kotlinx.serialization.*
@Serializable
data class Customer(val id: Int, val firstName: String, val lastName: String)以下の型のシリアライズ/デシリアライズは、kotlinx.serialization ライブラリによってサポートされています。
データの受信
リクエストのコンテンツを受信して変換するには、パラメータとしてデータクラスを受け取る receive メソッドを呼び出します。
post("/customer") {
val customer = call.receive<Customer>()
customerStorage.add(customer)
call.respondText("Customer stored correctly", status = HttpStatusCode.Created)リクエストの Content-Type は、リクエストを処理するための シリアライザー を選択するために使用されます。以下の例は、サーバー側で Customer オブジェクトに変換される JSON または XML データを含むサンプル HTTP クライアント リクエストを示しています。
POST http://0.0.0.0:8080/customer
Content-Type: application/json
{
"id": 3,
"firstName": "Jet",
"lastName": "Brains"
}POST http://0.0.0.0:8080/customer
Content-Type: application/xml
<Customer id="3" firstName="Jet" lastName="Brains"/>完全な例はこちらにあります:json-kotlinx。
データの送信
レスポンスでデータオブジェクトを渡すには、respond メソッドを使用できます。
routing {
get("/customer/{id}") {
val id: Int by call.parameters
val customer: Customer = customerStorage.find { it.id == id }!!
call.respond(customer)この場合、Ktor は Accept ヘッダーを使用して必要な シリアライザー を選択します。完全な例はこちらにあります:json-kotlinx。
カスタムシリアライザーの実装
Ktor では、データのシリアライズ/デシリアライズのために独自の シリアライザー を作成できます。これを行うには、ContentConverter インターフェースを実装する必要があります。
interface ContentConverter {
suspend fun serialize(contentType: ContentType, charset: Charset, typeInfo: TypeInfo, value: Any): OutgoingContent?
suspend fun deserialize(charset: Charset, typeInfo: TypeInfo, content: ByteReadChannel): Any?
}実装例として GsonConverter クラスを参考にしてください。
