title: Default Values sidebar_position: 3 id: default_values license: | Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License. You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

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:

  1. Detect default values using Kotlin reflection
  2. Apply default values during deserialization when fields are missing from serialized data
  3. 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