如何在Kotlin(Ktor)中编写通用数据序列化函数
Ktor泛型ServiceResult序列化与反序列化实现
原代码的核心问题
- 密封类
ServiceResult未标记@Serializable注解,导致整个结果类无法被序列化框架识别 - 泛型
T未添加可序列化约束,传入的类型未必能被Kotlinx Serialization处理 - 序列化时仅单独序列化
data字段,丢失了Success/Error的类型标记,反序列化时无法还原成原结果类型 - 测试用例错误地将序列化后的字符串直接与布尔值
true比较,序列化结果是字符串类型,需反序列化后再验证
修正后的完整实现
1. 定义可序列化的密封结果类
import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json import kotlin.reflect.KClass @Serializable sealed class ServiceResult<out T : @Serializable Any> { @Serializable data class Success<out T : @Serializable Any>(val data: T) : ServiceResult<T>() // Error分支无需泛型T,用Nothing表示无业务数据,语义更准确 @Serializable data class Error(val errorMessage: String) : ServiceResult<Nothing>() }
2. 序列化与反序列化函数
// 序列化:将ServiceResult转为JSON字符串,同时返回数据类型 inline fun <reified T : @Serializable Any> serializeServiceResult(result: ServiceResult<T>): Pair<String, KClass<T>> { return when (result) { is ServiceResult.Success -> Pair(Json.encodeToString(result), T::class) is ServiceResult.Error -> Pair(Json.encodeToString(result), T::class) } } // 反序列化:将JSON字符串还原为ServiceResult对象 inline fun <reified T : @Serializable Any> deserializeServiceResult(json: String): ServiceResult<T> { return Json.decodeFromString(json) }
正确的测试用例
import org.junit.Test import kotlin.test.assertEquals class MainTest { @Test fun booleanSuccessTest() { // 构造原始结果 val original = ServiceResult.Success(true) // 序列化 val (jsonStr, dataType) = serializeServiceResult(original) // 反序列化还原 val restored = deserializeServiceResult<Boolean>(jsonStr) // 验证还原后的结果 assert(restored is ServiceResult.Success) assertEquals(true, (restored as ServiceResult.Success<Boolean>).data) } @Test fun errorResultTest() { val originalError = ServiceResult.Error("请求超时") val (jsonStr, _) = serializeServiceResult<Nothing>(originalError) val restoredError = deserializeServiceResult<Nothing>(jsonStr) assert(restoredError is ServiceResult.Error) assertEquals("请求超时", (restoredError as ServiceResult.Error).errorMessage) } }
关键注意点
- 必须给
ServiceResult及其子类都添加@Serializable注解,序列化框架才能处理整个类结构 - 泛型
T要加@Serializable约束,确保传入的类型都是可序列化的 - 序列化时要序列化整个
Success/Error对象,不能仅序列化data字段——否则反序列化时无法区分是成功还是错误分支 - 测试时要走完整的序列化→反序列化流程,验证还原后的对象与原始数据一致
内容的提问来源于stack exchange,提问作者Денис Попков
相关产品推荐
相关产品推荐

