Skip to main content

Implementing Data Serialization

1. Using Parcelable Interface

The Parcelable interface in Android is used for efficiently serializing and deserializing objects, particularly useful when passing data between activities or services. It's more efficient than Serializable for Android-specific use cases.

Property Description Notes
writeToParcel(Parcel, Int) Writes the object's data to a Parcel. Must be implemented to define how the object is serialized.
describeContents() Returns the content description of the object. Typically returns 0 unless there are special content types.
CREATOR A Parcelable.Creator instance used to recreate the object from a Parcel. Must be implemented as a static field.

Example: Implementing Parcelable

import android.os.Parcel
import android.os.Parcelable

data class User(
    val name: String,
    val age: Int,
    val email: String
) : Parcelable {
    constructor(parcel: Parcel) : this(
        parcel.readString() ?: "",
        parcel.readInt(),
        parcel.readString() ?: ""
    )

    override fun writeToParcel(parcel: Parcel, flags: Int) {
        parcel.writeString(name)
        parcel.writeInt(age)
        parcel.writeString(email)
    }

    override fun describeContents(): Int = 0

    companion object CREATOR : Parcelable.Creator<User> {
        override fun createFromParcel(parcel: Parcel): User {
            return User(parcel)
        }

        override fun newArray(size: Int): Array<User?> {
            return arrayOfNulls(size)
        }
    }
}
Note: The Parcelable interface requires a special constructor that reads from a Parcel, and the CREATOR object must be implemented to support reconstruction of the object.
Warning: Parcelable is Android-specific and not suitable for cross-platform or general Java use. For generic serialization, consider using Serializable or libraries like Gson or Jackson.

2. Implementing Parcelable with @Parcelize

Example: Basic Parcelable Implementation

@Parcelize
data class User(
    val id: Int,
    val name: String,
    val email: String
) : Parcelable
Property Type Description
@Parcelize Annotation Marker annotation to automatically generate Parcelable implementation
data class Class Declaration Required for @Parcelize to work; must contain only immutable properties
Parcelable Interface Marker interface indicating the class can be serialized
Note: @Parcelize requires Kotlin Android Extensions plugin to be enabled.
Warning: Only basic types and other Parcelable objects can be used in @Parcelize.

Supported Types

  • String
  • Int, Long, Float, Double
  • Boolean
  • Char, Byte, Short
  • Array<T> where T is supported
  • List<T> where T is supported
  • Map<K, V> where K and V are supported
  • Parcelable objects

3. Using Serializable Interface

The Serializable interface in Kotlin is a marker interface that enables objects to be converted into a byte stream for persistence or transmission. It's particularly useful for saving and restoring object states, such as in Android's Bundle or when passing data between activities.

Property Description Notes
serialVersionUID A version UID to ensure compatibility during deserialization. Recommended for explicit control over serialization versions.

Example: Implementing Serializable in a Data Class

import java.io.Serializable

data class User(
    val name: String,
    val age: Int,
    val email: String
) : Serializable
Note: While Serializable is convenient, it's less efficient than alternatives like Parcelable for Android development. For better performance, consider using Parcelable.
Warning: When using Serializable, ensure that all fields in the class are serializable. Custom objects must also implement Serializable.

4. Working with JSON

Method Description Return Type Notes
Json.encodeToString() Serializes a Kotlin object to JSON string String Requires kotlinx.serialization dependency
Json.decodeFromString() Deserializes a JSON string to Kotlin object T Requires kotlinx.serialization dependency

Example: Serializing and Deserializing JSON

import kotlinx.serialization.*
import kotlinx.serialization.json.*

@Serializable
data class User(
    val id: Int,
    val name: String,
    val email: String
)

val user = User(1, "Alice", "alice@example.com")
val json = Json.encodeToString(user)
println(json) // {"id":1,"name":"Alice","email":"alice@example.com"}

val deserializedUser = Json.decodeFromString<User>(json)
println(deserializedUser) // User(id=1, name=Alice, email=alice@example.com)
Note: The @Serializable annotation is required for Kotlinx Serialization to work.
Warning: Ensure that all properties in the data class are serializable or marked with @Transient to avoid runtime errors.
Feature Description Support
Null Safety Handles null values gracefully in JSON Good
Type Safety Compile-time type checking for JSON structures Good
Custom Serializers Ability to define custom serialization logic Modern

5. Parsing JSON to Objects

Property Description Example
JsonParser Used to parse JSON strings into Kotlin objects val parser = Json { ignoreUnknownKeys = true }
decodeFromString Method to parse JSON string into a typed object val user = parser.decodeFromString<User>(jsonString)

Example: Parsing JSON to User Object

import kotlinx.serialization.json.*

data class User(
    val id: Int,
    val name: String,
    val email: String
)

val jsonString = """
{
  "id": 123,
  "name": "John Doe",
  "email": "john@example.com"
}
"""

val user = Json.decodeFromString<User>(jsonString)
println(user)
Note: Ensure the JSON structure matches the Kotlin data class properties exactly, or use ignoreUnknownKeys = true to skip unknown fields.

6. Serializing Objects to JSON

Property Type Description Default
json String Serialized JSON string representation of the object null
serializer KSerializer<T> Serializer instance for the type T null

Example: Serializing a Kotlin object to JSON

import kotlinx.serialization.*
import kotlinx.serialization.json.*

@Serializable
data class User(
    val id: Int,
    val name: String,
    val email: String
)

fun main() {
    val user = User(1, "John Doe", "john@example.com")
    val json = Json.encodeToString(user)
    println(json) // {"id":1,"name":"John Doe","email":"john@example.com"}
}

Example: Using custom JSON configuration

import kotlinx.serialization.*
import kotlinx.serialization.json.*

val customJson = Json {
    isLenient = true
    ignoreUnknownKeys = true
    encodeDefaults = false
}

@Serializable
data class Product(
    val id: Int,
    val name: String,
    val price: Double = 0.0
)

fun main() {
    val product = Product(101, "Laptop")
    val json = customJson.encodeToString(product)
    println(json) // {"id":101,"name":"Laptop"}
}
Note: The @Serializable annotation is required for Kotlin serialization to work with data classes.
Warning: When using encodeDefaults = false, fields with default values will not be included in the serialized JSON.

7. Using Gson Library

Feature Description Code Example
Gson JSON serialization/deserialization library for Java/Kotlin
val gson = Gson()
val json = gson.toJson(user)
val user = gson.fromJson(json, User::class.java)
JsonElement Represents a JSON element in the Gson library
val element = gson.toJsonTree(user)
val name = element.asJsonObject["name"].asString
Note: Gson is a popular library for serializing and deserializing JSON in Kotlin applications.
Warning: Gson does not support sealed classes natively. You may need to use custom serializers or adaptors for such cases.

Key Features of Gson

  • Easy serialization/deserialization of Java/Kotlin objects to/from JSON
  • Supports custom serializers and deserializers
  • Handles complex nested objects

8. Using Moshi Library

Example: Basic JSON Serialization with Moshi

import com.squareup.moshi.Moshi
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory

data class User(
    val id: Int,
    val name: String,
    val email: String
)

val moshi = Moshi.Builder()
    .add(KotlinJsonAdapterFactory())
    .build()

val adapter = moshi.adapter(User::class.java)

val user = User(1, "John Doe", "john@example.com")
val json = adapter.toJson(user)
println(json) // {"id":1,"name":"John Doe","email":"john@example.com"}

val userFromJson = adapter.fromJson(json)
println(userFromJson) // User(id=1, name=John Doe, email=john@example.com)
Feature Description Notes
Moshi.Builder() Creates a new Moshi instance Must be configured with appropriate adapters
add(KotlinJsonAdapterFactory()) Enables Kotlin-specific features Required for Kotlin data classes
adapter(T::class.java) Creates an adapter for a type Used to serialize/deserialize objects
Note: Moshi requires the KotlinJsonAdapterFactory to properly handle Kotlin data classes and nullability.
Warning: If KotlinJsonAdapterFactory is not added, Moshi will not correctly handle Kotlin-specific features like nullable properties.

Example: Custom Adapter for Date

import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.JsonClass
import java.text.SimpleDateFormat
import java.util.*

@JsonClass(generateAdapter = true)
data class Event(
    val id: Int,
    val title: String,
    @Json(name = "event_date")
    val eventDate: Date
)

val dateFormatter = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
val moshi = Moshi.Builder()
    .add(Date::class.java, dateFormatter)
    .build()

val adapter = moshi.adapter(Event::class.java)

val event = Event(1, "Android Dev Summit", Date())
val json = adapter.toJson(event)
println(json) // {"id":1,"title":"Android Dev Summit","event_date":"2026-04-05"}

9. Using Kotlinx Serialization

Kotlinx Serialization is a powerful library for serializing and deserializing data in Kotlin, particularly useful for converting objects to and from formats like JSON. It supports multiple formats and provides type-safe serialization.

Feature Description Notes
@Serializable Annotation to mark classes for serialization Must be applied to data classes or classes with serializable properties
@SerialName Customizes the serialized name of a property Useful for mapping between different naming conventions
@EncodeDefault Ensures default values are serialized Prevents omission of properties with default values
@Ignore Excludes a property from serialization Useful for sensitive or computed properties

Example: Basic Serialization

@Serializable
data class User(
    val id: Int,
    @SerialName("full_name") val name: String,
    val email: String
)

val user = User(1, "John Doe", "john@example.com")
val json = Json.encodeToString(user)
println(json) // {"id":1,"full_name":"John Doe","email":"john@example.com"}

Example: Deserialization

val json = """{"id":1,"full_name":"John Doe","email":"john@example.com"}"""
val user = Json.decodeFromString<User>(json)
println(user) // User(id=1, name=John Doe, email=john@example.com)
Note: The @SerialName annotation is useful when the property name in the serialized format differs from the Kotlin property name.
Warning: Ensure that all properties in a serializable class are either val or var, and that they support serialization (e.g., basic types, collections, or other serializable classes).
Format Support Notes
JSON NEW Supported Default format provided by the library
CBOR EXPERIMENTAL Supported Can be enabled with the kotlinx-serialization-cbor dependency
Protobuf DEPRECATED Supported in older versions Use kotlinx-serialization-protobuf for older versions

10. Handling Null Values in JSON

Property Description Default Behavior Handling Strategy
@SerializedName Defines the JSON field name for a property Uses Kotlin property name Use null to skip serialization
@JsonNull Explicitly marks a field as null in JSON Skips null fields by default Use null in Kotlin to represent JSON null
@JsonAdapter Customizes serialization for specific types No custom handling Implement JsonSerializer to control nulls

Example: Serializing Null Values

import com.google.gson.annotations.SerializedName

data class User(
    @SerializedName("name") val name: String?,
    @SerializedName("email") val email: String? = null,
    @SerializedName("age") val age: Int? = null
)

val user = User(name = "John Doe", email = null, age = 30)

Example: Custom Null Handling

import com.google.gson.*

class NullHandlingSerializer : JsonSerializer<String?> {
    override fun serialize(
        src: String?,
        typeOfSrc: Type,
        context: JsonSerializationContext
    ): JsonElement {
        return if (src == null) JsonNull.INSTANCE else JsonPrimitive(src)
    }
}

val gson = GsonBuilder()
    .registerTypeAdapter(String::class.java, NullHandlingSerializer())
    .create()
Note: By default, Gson skips null fields during serialization. Use @SerializedName or custom serializers to control how nulls are handled in JSON output.

Was this article helpful?