JSON serialization plugin for Ktor HTTP client (JVM platform)
—
Kotlinx Serialization-based JSON implementation for Ktor HTTP clients. Provides compile-time safe serialization with advanced features like polymorphism, custom serializers, and contextual serialization.
JsonSerializer implementation using kotlinx.serialization library for JSON processing.
/**
* A JsonSerializer implemented for kotlinx Serializable classes.
*/
@Deprecated("Please use ContentNegotiation plugin and its converters")
class KotlinxSerializer(private val json: Json = DefaultJson) : JsonSerializer {
/**
* Convert data object to OutgoingContent using kotlinx.serialization.
*/
override fun write(data: Any, contentType: ContentType): OutgoingContent
/**
* Read content from response using kotlinx.serialization deserialization.
*/
override fun read(type: TypeInfo, body: Input): Any
/**
* Internal method for content serialization.
*/
internal fun writeContent(data: Any): String
companion object {
/**
* Default Json configuration for KotlinxSerializer.
*/
val DefaultJson: Json
}
}Preconfigured Json instance with sensible defaults for HTTP client usage.
val DefaultJson: Json = Json {
isLenient = false
ignoreUnknownKeys = false
allowSpecialFloatingPointValues = true
useArrayPolymorphism = false
}The KotlinxSerializer is automatically discoverable on JVM through the ServiceLoader mechanism:
META-INF/services/io.ktor.client.plugins.json.JsonSerializer
io.ktor.client.plugins.kotlinx.serializer.KotlinxSerializerTo use KotlinxSerializer, add the kotlinx.serialization dependency:
Gradle
implementation("io.ktor:ktor-client-serialization:2.3.13")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1")Maven
<dependency>
<groupId>io.ktor</groupId>
<artifactId>ktor-client-serialization-jvm</artifactId>
<version>2.3.13</version>
</dependency>import io.ktor.client.*
import io.ktor.client.plugins.json.*
import io.ktor.client.plugins.kotlinx.serializer.*
import kotlinx.serialization.*
val client = HttpClient {
install(JsonPlugin) {
serializer = KotlinxSerializer()
}
}import kotlinx.serialization.json.*
val client = HttpClient {
install(JsonPlugin) {
serializer = KotlinxSerializer(Json {
prettyPrint = true
isLenient = true
ignoreUnknownKeys = true
coerceInputValues = true
useAlternativeNames = false
namingStrategy = JsonNamingStrategy.SnakeCase
explicitNulls = false
})
}
}import kotlinx.serialization.*
@Serializable
data class User(
val id: Long,
val name: String,
val email: String,
@SerialName("created_at")
val createdAt: String
)
// POST request - automatic serialization
val response = client.post("https://api.example.com/users") {
contentType(ContentType.Application.Json)
setBody(User(0, "Alice", "alice@example.com", "2023-01-01"))
}
// GET request - automatic deserialization
val user: User = client.get("https://api.example.com/users/1").body()@Serializable
sealed class Animal {
abstract val name: String
}
@Serializable
@SerialName("dog")
data class Dog(
override val name: String,
val breed: String
) : Animal()
@Serializable
@SerialName("cat")
data class Cat(
override val name: String,
val color: String
) : Animal()
// Usage
val animals: List<Animal> = listOf(
Dog("Buddy", "Golden Retriever"),
Cat("Whiskers", "Orange")
)
val response = client.post("https://api.example.com/animals") {
contentType(ContentType.Application.Json)
setBody(animals)
}import kotlinx.serialization.*
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
@Serializer(forClass = LocalDateTime::class)
object LocalDateTimeSerializer : KSerializer<LocalDateTime> {
private val formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME
override val descriptor: SerialDescriptor =
PrimitiveSerialDescriptor("LocalDateTime", PrimitiveKind.STRING)
override fun serialize(encoder: Encoder, value: LocalDateTime) {
encoder.encodeString(value.format(formatter))
}
override fun deserialize(decoder: Decoder): LocalDateTime {
return LocalDateTime.parse(decoder.decodeString(), formatter)
}
}
@Serializable
data class Event(
val id: Long,
val name: String,
@Serializable(with = LocalDateTimeSerializer::class)
val timestamp: LocalDateTime
)// Define contextual serializer
val module = SerializersModule {
contextual(LocalDateTime::class, LocalDateTimeSerializer)
}
val client = HttpClient {
install(JsonPlugin) {
serializer = KotlinxSerializer(Json {
serializersModule = module
})
}
}
@Serializable
data class Event(
val id: Long,
val name: String,
@Contextual
val timestamp: LocalDateTime
)// List serialization
@Serializable
data class UserList(val users: List<User>)
// Map serialization
@Serializable
data class UserMap(val users: Map<String, User>)
// Direct collection serialization
val users: List<User> = client.get("https://api.example.com/users").body()
val userMap: Map<String, User> = client.get("https://api.example.com/users/map").body()import kotlinx.serialization.*
try {
val user: User = client.get("https://api.example.com/users/1").body()
} catch (e: SerializationException) {
// Serialization/deserialization error
logger.error("JSON serialization error", e)
} catch (e: MissingFieldException) {
// Required field missing
logger.error("Missing required field", e)
} catch (e: UnknownKeyException) {
// Unknown key in JSON (when ignoreUnknownKeys = false)
logger.error("Unknown JSON key", e)
}val client = HttpClient {
install(JsonPlugin) {
serializer = KotlinxSerializer(Json {
// Parsing options
isLenient = true // Allow lenient parsing
ignoreUnknownKeys = true // Ignore unknown JSON keys
coerceInputValues = true // Coerce invalid values to defaults
// Output options
prettyPrint = true // Pretty print JSON
prettyPrintIndent = " " // Custom indent
// Null handling
explicitNulls = false // Don't encode null values
// Naming strategy
namingStrategy = JsonNamingStrategy.SnakeCase
// Special values
allowSpecialFloatingPointValues = true // Allow NaN, Infinity
allowStructuredMapKeys = true // Allow complex map keys
// Polymorphism
useArrayPolymorphism = false // Use object polymorphism
// Custom serializers module
serializersModule = SerializersModule {
contextual(LocalDateTime::class, LocalDateTimeSerializer)
polymorphic(Animal::class) {
subclass(Dog::class)
subclass(Cat::class)
}
}
})
}
}The KotlinxSerializer supports extensive Json configuration:
isLenient: Allow lenient JSON parsingignoreUnknownKeys: Ignore unknown propertiescoerceInputValues: Coerce invalid input to defaultsallowStructuredMapKeys: Allow non-primitive map keysallowSpecialFloatingPointValues: Allow NaN and InfinityprettyPrint: Enable pretty printingprettyPrintIndent: Custom indentation stringexplicitNulls: Control null value encodingserializersModule: Custom serializers and polymorphismnamingStrategy: Field naming strategyuseArrayPolymorphism: Polymorphism format choice@Serializable annotation for compile-time code generationInstall with Tessl CLI
npx tessl i tessl/maven-io-ktor--ktor-client-json-jvm