overview
Kotlinx Serialization and @Serializable
Annotation
Overview
Kotlinx Serialization is a Kotlin library that provides a multiplatform and idiomatic way to serialize and deserialize Kotlin objects. It supports various formats such as JSON, ProtoBuf, CBOR, and more. The library is designed to work seamlessly with Kotlin's data classes and sealed classes, ensuring type safety and ease of use.
@Serializable
Annotation
The @Serializable
annotation is the cornerstone of Kotlinx Serialization. It marks a class for automatic generation of serialization and deserialization code. By annotating a class with @Serializable
, you enable it to be easily converted to and from JSON (or other formats supported by the library).
Usage
Annotating Data Classes
To use @Serializable
, simply annotate your Kotlin data class:
import kotlinx.serialization.Serializable
@Serializable
data class User(val name: String, val age: Int)
Serialization and Deserialization
Once a class is annotated, you can use the provided serialization and deserialization functions:
import kotlinx.serialization.json.Json
fun main() {
val user = User("Alice", 30)
// Serialize to JSON
val jsonString = Json.encodeToString(User.serializer(), user)
println(jsonString) // Output: {"name":"Alice","age":30}
// Deserialize from JSON
val deserializedUser = Json.decodeFromString(User.serializer(), jsonString)
println(deserializedUser) // Output: User(name=Alice, age=30)
}
Custom Serialization
You can also define custom serialization logic by implementing the KSerializer
interface or using the @Serializable
with custom serializers:
import kotlinx.serialization.*
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
@Serializable
data class User(val name: String, val age: Int)
object UserSerializer : KSerializer<User> {
override val descriptor: SerialDescriptor = buildClassSerialDescriptor("User") {
element<String>("name")
element<Int>("age")
}
override fun serialize(encoder: Encoder, value: User) {
val composite = encoder.beginStructure(descriptor)
composite.encodeStringElement(descriptor, 0, value.name)
composite.encodeIntElement(descriptor, 1, value.age)
composite.endStructure(descriptor)
}
override fun deserialize(decoder: Decoder): User {
val dec = decoder.beginStructure(descriptor)
var name = ""
var age = 0
loop@ while (true) {
when (val index = dec.decodeElementIndex(descriptor)) {
0 -> name = dec.decodeStringElement(descriptor, 0)
1 -> age = dec.decodeIntElement(descriptor, 1)
CompositeDecoder.DECODE_DONE -> break@loop
else -> throw SerializationException("Unknown index $index")
}
}
dec.endStructure(descriptor)
return User(name, age)
}
}
fun main() {
val user = User("Alice", 30)
// Serialize with custom serializer
val jsonString = Json.encodeToString(UserSerializer, user)
println(jsonString) // Output: {"name":"Alice","age":30}
// Deserialize with custom serializer
val deserializedUser = Json.decodeFromString(UserSerializer, jsonString)
println(deserializedUser) // Output: User(name=Alice, age=30)
}
Benefits
- Multiplatform Support: Works across JVM, JavaScript, and Native platforms.
- Type Safety: Ensures that your data conforms to the expected types.
- Integration with Kotlin Features: Works seamlessly with data classes, sealed classes, and other Kotlin features.
- Extensibility: Allows custom serialization logic for complex use cases.
Conclusion
Kotlinx Serialization, with its @Serializable
annotation, provides a powerful and flexible way to handle serialization in a Kotlin-centric manner. It offers multiplatform support, type safety, and ease of use, making it a go-to choice for Kotlin developers looking to serialize and deserialize their data effectively.
Backlinks