You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Kotlin(Ktor)中编写通用数据序列化函数

Ktor泛型ServiceResult序列化与反序列化实现

原代码的核心问题

  1. 密封类ServiceResult未标记@Serializable注解,导致整个结果类无法被序列化框架识别
  2. 泛型T未添加可序列化约束,传入的类型未必能被Kotlinx Serialization处理
  3. 序列化时仅单独序列化data字段,丢失了Success/Error的类型标记,反序列化时无法还原成原结果类型
  4. 测试用例错误地将序列化后的字符串直接与布尔值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,提问作者Денис Попков

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 12:17:50