A Kotlin multiplatform library for JSON serialization providing type-safe JSON parsing and object serialization
—
Comprehensive configuration system for customizing JSON serialization behavior, formatting options, and parsing rules through the JsonBuilder and JsonConfiguration classes.
Mutable builder for creating Json instances with custom configuration options.
/**
* Builder for creating Json instances with custom configuration
*/
class JsonBuilder {
/**
* Whether to encode properties with default values
* Default: false
*/
var encodeDefaults: Boolean
/**
* Whether to encode explicit null values
* Default: true
*/
var explicitNulls: Boolean
/**
* Whether to ignore unknown JSON properties during deserialization
* Default: false
*/
var ignoreUnknownKeys: Boolean
/**
* Whether to use relaxed parsing mode allowing unquoted keys and values
* Default: false
*/
var isLenient: Boolean
/**
* Whether to format output JSON with indentation and line breaks
* Default: false
*/
var prettyPrint: Boolean
/**
* Custom indentation string for pretty printing
* Default: " " (4 spaces)
*/
@ExperimentalSerializationApi
var prettyPrintIndent: String
/**
* Whether to coerce incorrect input types during deserialization
* Default: false
*/
var coerceInputValues: Boolean
/**
* Property name for polymorphic type discriminator
* Default: "type"
*/
var classDiscriminator: String
/**
* Mode controlling when class discriminator is included
* Default: ClassDiscriminatorMode.POLYMORPHIC
*/
@ExperimentalSerializationApi
var classDiscriminatorMode: ClassDiscriminatorMode
/**
* Whether to allow special floating point values (NaN, Infinity)
* Default: false
*/
var allowSpecialFloatingPointValues: Boolean
/**
* Whether to allow non-primitive map keys (serialized as arrays)
* Default: false
*/
var allowStructuredMapKeys: Boolean
/**
* Whether to use array format for polymorphic serialization
* Default: false
*/
var useArrayPolymorphism: Boolean
/**
* Whether to use alternative names specified by @JsonNames
* Default: true
*/
var useAlternativeNames: Boolean
/**
* Strategy for transforming property names during serialization
* Default: null (no transformation)
*/
@ExperimentalSerializationApi
var namingStrategy: JsonNamingStrategy?
/**
* Whether to decode enum values case-insensitively
* Default: false
*/
@ExperimentalSerializationApi
var decodeEnumsCaseInsensitive: Boolean
/**
* Whether to allow trailing commas in objects and arrays
* Default: false
*/
@ExperimentalSerializationApi
var allowTrailingComma: Boolean
/**
* Whether to allow C/C++ style comments in JSON
* Default: false
*/
@ExperimentalSerializationApi
var allowComments: Boolean
/**
* Module containing custom serializers for types
* Default: EmptySerializersModule
*/
var serializersModule: SerializersModule
}Immutable configuration instance containing all JSON processing settings.
/**
* Immutable configuration for Json instances
* Contains all serialization and deserialization settings
*/
class JsonConfiguration {
val encodeDefaults: Boolean
val explicitNulls: Boolean
val ignoreUnknownKeys: Boolean
val isLenient: Boolean
val prettyPrint: Boolean
val coerceInputValues: Boolean
val classDiscriminator: String
val allowSpecialFloatingPointValues: Boolean
val allowStructuredMapKeys: Boolean
val useArrayPolymorphism: Boolean
val useAlternativeNames: Boolean
// Additional configuration properties...
}Basic Configuration:
import kotlinx.serialization.json.*
// Simple configuration
val json = Json {
prettyPrint = true
ignoreUnknownKeys = true
}
// Lenient parsing for relaxed JSON
val lenientJson = Json {
isLenient = true
coerceInputValues = true
ignoreUnknownKeys = true
}
// Production configuration
val productionJson = Json {
encodeDefaults = false
explicitNulls = false
ignoreUnknownKeys = true
coerceInputValues = true
}Control how Kotlin objects are serialized to JSON.
var encodeDefaults: Boolean
var explicitNulls: Boolean
var prettyPrint: Boolean
@ExperimentalSerializationApi
var prettyPrintIndent: StringUsage Examples:
import kotlinx.serialization.*
import kotlinx.serialization.json.*
@Serializable
data class User(
val name: String,
val age: Int = 25,
val email: String? = null,
val active: Boolean = true
)
val user = User("Alice", email = "alice@example.com")
// Default encoding (no defaults, explicit nulls)
val defaultJson = Json
val default = defaultJson.encodeToString(user)
// Result: {"name":"Alice","email":"alice@example.com"}
// Encode defaults and explicit nulls
val verboseJson = Json {
encodeDefaults = true
explicitNulls = true
}
val verbose = verboseJson.encodeToString(user)
// Result: {"name":"Alice","age":25,"email":"alice@example.com","active":true}
// Pretty printing
val prettyJson = Json {
prettyPrint = true
encodeDefaults = true
}
val pretty = prettyJson.encodeToString(user)
// Result:
// {
// "name": "Alice",
// "age": 25,
// "email": "alice@example.com",
// "active": true
// }
// Custom indentation (experimental)
val customIndentJson = Json {
prettyPrint = true
prettyPrintIndent = " " // 2 spaces instead of 4
}Control how JSON is parsed and deserialized to Kotlin objects.
var ignoreUnknownKeys: Boolean
var isLenient: Boolean
var coerceInputValues: Boolean
@ExperimentalSerializationApi
var decodeEnumsCaseInsensitive: Boolean
@ExperimentalSerializationApi
var allowTrailingComma: Boolean
@ExperimentalSerializationApi
var allowComments: BooleanUsage Examples:
import kotlinx.serialization.*
import kotlinx.serialization.json.*
@Serializable
data class Config(val timeout: Int, val enabled: Boolean)
// Strict parsing (default)
val strictJson = Json
try {
val config = strictJson.decodeFromString<Config>("""
{
"timeout": 30,
"enabled": true,
"extra": "ignored" // This will cause an error
}
""")
} catch (e: Exception) {
// SerializationException: Encountered unknown key 'extra'
}
// Ignore unknown keys
val flexibleJson = Json {
ignoreUnknownKeys = true
}
val config1 = flexibleJson.decodeFromString<Config>("""
{
"timeout": 30,
"enabled": true,
"extra": "ignored" // This is now ignored
}
""")
// Lenient parsing allows unquoted keys and values
val lenientJson = Json {
isLenient = true
}
val config2 = lenientJson.decodeFromString<Config>("""
{
timeout: 30, // Unquoted key
enabled: true
}
""")
// Coerce input values
val coercingJson = Json {
coerceInputValues = true
}
val config3 = coercingJson.decodeFromString<Config>("""
{
"timeout": "30", // String coerced to Int
"enabled": 1 // Number coerced to Boolean
}
""")
// Allow trailing commas and comments (experimental)
val relaxedJson = Json {
allowTrailingComma = true
allowComments = true
}
val config4 = relaxedJson.decodeFromString<Config>("""
{
// Configuration settings
"timeout": 30,
"enabled": true, // Trailing comma allowed
}
""")Control how polymorphic types are serialized and deserialized.
var classDiscriminator: String
@ExperimentalSerializationApi
var classDiscriminatorMode: ClassDiscriminatorMode
var useArrayPolymorphism: Boolean
enum class ClassDiscriminatorMode {
NONE, ALL_JSON_OBJECTS, POLYMORPHIC
}Usage Examples:
import kotlinx.serialization.*
import kotlinx.serialization.json.*
@Serializable
sealed class Shape {
abstract val area: Double
}
@Serializable
@SerialName("circle")
data class Circle(val radius: Double) : Shape() {
override val area: Double get() = 3.14159 * radius * radius
}
@Serializable
@SerialName("rectangle")
data class Rectangle(val width: Double, val height: Double) : Shape() {
override val area: Double get() = width * height
}
val shapes = listOf<Shape>(
Circle(5.0),
Rectangle(4.0, 3.0)
)
// Default polymorphic serialization
val defaultJson = Json {
classDiscriminator = "type"
}
val default = defaultJson.encodeToString(shapes)
// Result: [{"type":"circle","radius":5.0},{"type":"rectangle","width":4.0,"height":3.0}]
// Custom discriminator name
val customJson = Json {
classDiscriminator = "kind"
}
val custom = customJson.encodeToString(shapes)
// Result: [{"kind":"circle","radius":5.0},{"kind":"rectangle","width":4.0,"height":3.0}]
// Array polymorphism
val arrayJson = Json {
useArrayPolymorphism = true
}
val array = arrayJson.encodeToString(shapes)
// Result: [["circle",{"radius":5.0}],["rectangle",{"width":4.0,"height":3.0}]]
// Control discriminator inclusion mode (experimental)
val allObjectsJson = Json {
classDiscriminatorMode = ClassDiscriminatorMode.ALL_JSON_OBJECTS
}Configure handling of special floating-point values and complex map keys.
var allowSpecialFloatingPointValues: Boolean
var allowStructuredMapKeys: BooleanUsage Examples:
import kotlinx.serialization.*
import kotlinx.serialization.json.*
@Serializable
data class FloatData(val value: Double, val ratio: Float)
@Serializable
data class ComplexKey(val x: Int, val y: Int)
// Special floating point values
val specialJson = Json {
allowSpecialFloatingPointValues = true
}
val floatData = FloatData(Double.NaN, Float.POSITIVE_INFINITY)
val encoded = specialJson.encodeToString(floatData)
// Result: {"value":NaN,"ratio":Infinity}
// Structured map keys
val structuredJson = Json {
allowStructuredMapKeys = true
}
val complexMap = mapOf(
ComplexKey(1, 2) to "point1",
ComplexKey(3, 4) to "point2"
)
val mapEncoded = structuredJson.encodeToString(complexMap)
// Result: [["{"x":1,"y":2}","point1"],["{"x":3,"y":4}","point2"]]Configure property name transformation during serialization.
@ExperimentalSerializationApi
var namingStrategy: JsonNamingStrategy?
var useAlternativeNames: Boolean
fun interface JsonNamingStrategy {
fun serialNameForJson(descriptor: SerialDescriptor, elementIndex: Int, serialName: String): String
companion object {
val SnakeCase: JsonNamingStrategy
val KebabCase: JsonNamingStrategy
}
}Usage Examples:
import kotlinx.serialization.*
import kotlinx.serialization.json.*
@Serializable
data class UserProfile(
val firstName: String,
val lastName: String,
val emailAddress: String,
val phoneNumber: String?
)
val user = UserProfile("John", "Doe", "john@example.com", "555-1234")
// Snake case naming
val snakeCaseJson = Json {
namingStrategy = JsonNamingStrategy.SnakeCase
}
val snakeCase = snakeCaseJson.encodeToString(user)
// Result: {"first_name":"John","last_name":"Doe","email_address":"john@example.com","phone_number":"555-1234"}
// Kebab case naming
val kebabCaseJson = Json {
namingStrategy = JsonNamingStrategy.KebabCase
}
val kebabCase = kebabCaseJson.encodeToString(user)
// Result: {"first-name":"John","last-name":"Doe","email-address":"john@example.com","phone-number":"555-1234"}
// Alternative names with @JsonNames
@Serializable
data class ApiResponse(
@JsonNames("user_id", "userId")
val id: Int,
val message: String
)
val alternativeJson = Json {
useAlternativeNames = true
}
// Can decode from any of: "id", "user_id", or "userId"
val response1 = alternativeJson.decodeFromString<ApiResponse>("""{"user_id":123,"message":"success"}""")
val response2 = alternativeJson.decodeFromString<ApiResponse>("""{"userId":123,"message":"success"}""")Configure custom serializers and type handling.
var serializersModule: SerializersModuleUsage Examples:
import kotlinx.serialization.*
import kotlinx.serialization.json.*
import kotlinx.serialization.modules.*
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
// Custom serializer for LocalDateTime
object LocalDateTimeSerializer : KSerializer<LocalDateTime> {
private val formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME
override val descriptor = PrimitiveSerialDescriptor("LocalDateTime", PrimitiveKind.STRING)
override fun serialize(encoder: Encoder, value: LocalDateTime) = encoder.encodeString(value.format(formatter))
override fun deserialize(decoder: Decoder): LocalDateTime = LocalDateTime.parse(decoder.decodeString(), formatter)
}
@Serializable
data class Event(
val name: String,
@Serializable(LocalDateTimeSerializer::class)
val timestamp: LocalDateTime
)
// Configure Json with custom serializers
val customJson = Json {
serializersModule = SerializersModule {
contextual(LocalDateTime::class, LocalDateTimeSerializer)
}
}
val event = Event("Meeting", LocalDateTime.now())
val encoded = customJson.encodeToString(event)
val decoded = customJson.decodeFromString<Event>(encoded)Json instances can inherit configuration from other instances.
import kotlinx.serialization.json.*
// Base configuration
val baseJson = Json {
ignoreUnknownKeys = true
isLenient = true
}
// Inherit and extend configuration
val extendedJson = Json(from = baseJson) {
prettyPrint = true
encodeDefaults = true
// ignoreUnknownKeys and isLenient are inherited
}
// Production vs Development configurations
val developmentJson = Json {
prettyPrint = true
encodeDefaults = true
allowComments = true
allowTrailingComma = true
}
val productionJson = Json(from = developmentJson) {
prettyPrint = false
allowComments = false
allowTrailingComma = false
// Other settings inherited from development
}Install with Tessl CLI
npx tessl i tessl/maven-org-jetbrains-kotlinx--kotlinx-serialization-json-jvm