跳到主要内容
版本:1.6.0

默认值

启用兼容模式时,Fory 在原生模式反序列化过程中支持 Kotlin 数据类默认值。该功能可在数据类 Schema 演进时实现向前/向后兼容。

概述

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

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

使用方式

以下情况下可以使用此功能:

  • 原生模式 Fory 实例启用了兼容模式。使用 withXlang(false) 时默认如此。
  • 通过 ForyKotlin.builder()Fory.builder().withModule(ForyKotlin) 构建 Fory 实例, 并启用了原生模式
  • 序列化数据中缺少某个字段,但该字段存在于目标类中且具有默认值

示例

import org.apache.fory.kotlin.ForyKotlin

// 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 = ForyKotlin.builder().withXlang(false)
.build()
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)
}

支持的默认值类型

默认值支持以下类型:

  • 基本类型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 = ForyKotlin.builder().withXlang(false)
.build()

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

相关主题