跳到主要内容
版本:0.14

默认值

在使用兼容模式时,Fory 支持在反序列化期间处理 Kotlin 数据类的默认值。此特性使得数据类 schema 演化时能够保持前向/后向兼容性。

概述

当 Kotlin 数据类具有带默认值的参数时,Fory 可以:

  1. 检测默认值:使用 Kotlin 反射
  2. 应用默认值:当序列化数据中缺少字段时,在反序列化期间应用默认值
  3. 支持 schema 演化:允许添加带默认值的新字段,而不会破坏现有的序列化数据

用法

在以下情况下,此特性会自动启用:

  • 启用了兼容模式(withCompatibleMode(CompatibleMode.COMPATIBLE)
  • 已注册 Kotlin 序列化器(KotlinSerializers.registerSerializers(fory)
  • 序列化数据中缺少某个字段,但目标类中该字段存在并具有默认值

示例

import org.apache.fory.Fory
import org.apache.fory.config.CompatibleMode
import org.apache.fory.serializer.kotlin.KotlinSerializers

// 原始数据类
data class User(val name: String, val age: Int)

// 演化后的数据类,带有新字段和默认值
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)

// 使用旧 schema 序列化
val oldUser = User("John", 30)
val serialized = fory.serialize(oldUser)

// 使用新 schema 反序列化 - 缺失的字段获得默认值
val newUser = fory.deserialize(serialized) as UserV2
println(newUser) // UserV2(name=John, age=30, email=default@example.com)
}

支持的默认值类型

以下类型支持默认值:

  • 原始类型IntLongDoubleFloatBooleanByteShortChar
  • 无符号类型UIntULongUByteUShort
  • 字符串String
  • 集合ListSetMap(带默认实例)
  • 自定义对象:任何可以通过反射实例化的对象

复杂的默认值

默认值可以是复杂的表达式:

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

可空字段与默认值

也支持带默认值的可空字段:

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 (默认值)
// deserialized.age == null (默认值)

相关主题