Kotlin Serialization Annotations for JSON Mapping

Master kotlinx.serialization annotations like @Serializable, @SerialName, @Transient, and @EncodeDefault to control how Kotlin data classes map to JSON fields.

Serialization

Detailed Explanation

kotlinx.serialization Annotations

Kotlin's official serialization library uses annotations to control how data classes are encoded to and decoded from JSON. Understanding these annotations is essential for precise JSON mapping.

Core Annotations

@Serializable
data class User(
    @SerialName("user_id")
    val userId: Int,

    val name: String,

    @Transient
    val cachedHash: Int = 0,

    @EncodeDefault
    val role: String = "viewer",

    @Required
    val email: String
)

Annotation Reference

Annotation Purpose
@Serializable Marks class for serialization; generates serializer
@SerialName("key") Maps a property to a different JSON key
@Transient Excludes property from serialization entirely
@EncodeDefault Includes property in output even when it matches the default
@Required Makes field mandatory during deserialization (no default)

@SerialName for Key Mapping

Most JSON APIs use snake_case while Kotlin uses camelCase:

@Serializable
data class Event(
    @SerialName("event_id") val eventId: String,
    @SerialName("created_at") val createdAt: String,
    @SerialName("is_public") val isPublic: Boolean
)

@Transient for Internal Fields

@Serializable
data class CachedUser(
    val id: Int,
    val name: String,
    @Transient
    val fetchedAt: Long = System.currentTimeMillis()
)

The fetchedAt field exists in the Kotlin object but never appears in JSON output and is never read from JSON input. It must have a default value.

@EncodeDefault Modes

@Serializable
data class Settings(
    @EncodeDefault(EncodeDefault.Mode.ALWAYS)
    val theme: String = "light",

    @EncodeDefault(EncodeDefault.Mode.NEVER)
    val internal: String = "default"
)
  • ALWAYS -- include in JSON even when equal to default
  • NEVER -- omit from JSON when equal to default (this is the global default behavior)

Combining Annotations

@Serializable
data class ApiConfig(
    @SerialName("base_url")
    @Required
    val baseUrl: String,

    @SerialName("retry_count")
    @EncodeDefault
    val retryCount: Int = 3
)

These annotations give you full control over the JSON-to-Kotlin mapping without modifying the JSON source.

Use Case

When integrating with third-party APIs that use snake_case naming, @SerialName annotations let your Kotlin code follow camelCase conventions while correctly mapping to the API's field names. @Transient is essential for computed or cached fields that should not leak into network payloads.

Try It — JSON to Kotlin

Open full tool