
jvmMain.GsonConverter.kt Maven / Gradle / Ivy
/*
* Copyright 2014-2021 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
*/
package io.ktor.serialization.gson
import com.google.gson.*
import io.ktor.http.*
import io.ktor.http.content.*
import io.ktor.serialization.*
import io.ktor.util.reflect.*
import io.ktor.utils.io.*
import io.ktor.utils.io.charsets.*
import io.ktor.utils.io.jvm.javaio.*
import kotlinx.coroutines.*
import kotlin.reflect.*
import kotlin.reflect.jvm.*
/**
* A GSON converter for the [ContentNegotiation] plugin.
*/
public class GsonConverter(private val gson: Gson = Gson()) : ContentConverter {
@Suppress("OverridingDeprecatedMember")
@Deprecated(
"Please override and use serializeNullable instead",
level = DeprecationLevel.WARNING,
replaceWith = ReplaceWith("serializeNullable(charset, typeInfo, contentType, value)")
)
override suspend fun serialize(
contentType: ContentType,
charset: Charset,
typeInfo: TypeInfo,
value: Any
): OutgoingContent {
return serializeNullable(contentType, charset, typeInfo, value)
}
override suspend fun serializeNullable(
contentType: ContentType,
charset: Charset,
typeInfo: TypeInfo,
value: Any?
): OutgoingContent {
return TextContent(gson.toJson(value), contentType.withCharsetIfNeeded(charset))
}
override suspend fun deserialize(charset: Charset, typeInfo: TypeInfo, content: ByteReadChannel): Any? {
if (gson.isExcluded(typeInfo.type)) {
throw ExcludedTypeGsonException(typeInfo.type)
}
try {
return withContext(Dispatchers.IO) {
val reader = content.toInputStream().reader(charset)
gson.fromJson(reader, typeInfo.reifiedType)
}
} catch (deserializeFailure: JsonSyntaxException) {
throw JsonConvertException("Illegal json parameter found", deserializeFailure)
}
}
}
@Suppress("DEPRECATION")
internal fun Gson.isExcluded(type: KClass<*>) =
excluder().excludeClass(type.java, false)
@OptIn(ExperimentalCoroutinesApi::class)
internal class ExcludedTypeGsonException(
private val type: KClass<*>
) : Exception("Type ${type.jvmName} is excluded so couldn't be used in receive"),
CopyableThrowable {
override fun createCopy(): ExcludedTypeGsonException = ExcludedTypeGsonException(type).also {
it.initCause(this)
}
}
/**
* Registers the `application/json` content type to the [ContentNegotiation] plugin using GSON.
*
* You can learn more from [Content negotiation and serialization](https://ktor.io/docs/serialization.html).
*/
public fun Configuration.gson(
contentType: ContentType = ContentType.Application.Json,
block: GsonBuilder.() -> Unit = {}
) {
val builder = GsonBuilder()
builder.apply(block)
val converter = GsonConverter(builder.create())
register(contentType, converter)
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy