Default Values
Fory supports Kotlin data class default values during deserialization when using compatible mode. This feature enables forward/backward compatibility when data class schemas evolve.
Overview
When a Kotlin data class has parameters with default values, Fory can:
- Detect default values using Kotlin reflection
- Apply default values during deserialization when fields are missing from serialized data
- Support schema evolution by allowing new fields with defaults to be added without breaking existing serialized data
Usage
This feature is automatically enabled when:
- Compatible mode is enabled (
withCompatibleMode(CompatibleMode.COMPATIBLE)) - Kotlin serializers are registered (
KotlinSerializers.registerSerializers(fory)) - A field is missing from the serialized data but exists in the target class with a default value
Example
import org.apache.fory.Fory
import org.apache.fory.config.CompatibleMode
import org.apache.fory.serializer.kotlin.KotlinSerializers
// Original data class
data class User(val name: String, val age: Int)
// Evolved data class with new field and default value
data class UserV2(val name: String, val age: Int, val email: String = "default@example.com")
fun main() {
val fory = Fory.builder()
.withCompatibleMode(CompatibleMode.COMPATIBLE)
.build()
KotlinSerializers.registerSerializers(fory)
fory.register(User::class.java)
fory.register(UserV2::class.java)
// Serialize with old schema
val oldUser = User("John", 30)
val serialized = fory.serialize(oldUser)
// Deserialize with new schema - missing field gets default value
val newUser = fory.deserialize(serialized) as UserV2
println(newUser) // UserV2(name=John, age=30, email=default@example.com)
}
Supported Default Value Types
The following types are supported for default values:
- Primitive types:
Int,Long,Double,Float,Boolean,Byte,Short,Char - Unsigned types:
UInt,ULong,UByte,UShort - String:
String - Collections:
List,Set,Map(with default instances) - Custom objects: Any object that can be instantiated via reflection
Complex Default Values
Default values can be complex expressions:
data class ConfigV1(val name: String)
data class ConfigV2(
val name: String,
val settings: Map<String, String> = mapOf("default" to "value"),
val tags: List<String> = listOf("default"),
val enabled: Boolean = true,
val retryCount: Int = 3
)
val fory = Fory.builder()
.withCompatibleMode(CompatibleMode.COMPATIBLE)
.build()
KotlinSerializers.registerSerializers(fory)
val original = ConfigV1("myConfig")
val serialized = fory.serialize(original)
val deserialized = fory.deserialize(serialized) as ConfigV2
// deserialized.name == "myConfig"
// deserialized.settings == mapOf("default" to "value")
// deserialized.tags == listOf("default")
// deserialized.enabled == true
// deserialized.retryCount == 3
Nullable Fields with Defaults
Nullable fields with default values are also supported:
data class PersonV1(val name: String)
data class PersonV2(
val name: String,
val nickname: String? = null,
val age: Int? = null
)
val original = PersonV1("John")
val serialized = fory.serialize(original)
val deserialized = fory.deserialize(serialized) as PersonV2
// deserialized.name == "John"
// deserialized.nickname == null (default)
// deserialized.age == null (default)
Related Topics
- Schema Evolution - Forward/backward compatibility in Java
- Fory Creation - Setting up Fory with compatible mode