Kotlin中序列化任意对象为base64字符串报错该如何修复?
错误原因
kotlinx.serialization 是编译期静态生成序列化逻辑的框架,你直接调用Json.encodeToString(input)时传入Any类型的实例,编译器无法提前确定input的实际类型,找不到对应的序列化器,就会抛出该报错。此外你现有代码的finally块中强制返回空字符串,就算序列化逻辑执行成功也永远会返回空值,这个逻辑漏洞需要一并修复。
修复方案
方案1:泛型+序列化约束(推荐,保留类型安全)
如果调用方法时可以确定传入实例的类型,建议把方法改为泛型实现,要求传入类型标记@Serializable注解:
import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json import org.slf4j.Logger import org.slf4j.LoggerFactory import java.util.Base64 class SerializerAdapter: SerializerPort { private val logger: Logger = LoggerFactory.getLogger(javaClass.simpleName) override fun <T @Serializable Any> toBase64(input: T): String { return try { val jsonString = Json.encodeToString(input) Base64.getEncoder().encodeToString(jsonString.toByteArray()) } catch (ex: Exception) { logger.error("[BASE64 Error] error converting json object to base64 encoded string: ${ex.stackTraceToString()}") "" } } }
如果SerializerPort接口的方法签名不允许修改,可以改为调用时显式传入序列化器:
import kotlinx.serialization.KSerializer import kotlinx.serialization.json.Json override fun <T> toBase64(input: T, serializer: KSerializer<T>): String { return try { val jsonString = Json.encodeToString(serializer, input) Base64.getEncoder().encodeToString(jsonString.toByteArray()) } catch (ex: Exception) { logger.error("[BASE64 Error] error converting json object to base64 encoded string: ${ex.stackTraceToString()}") "" } }
方案2:运行时动态获取序列化器(适用于必须使用Any作为入参的场景)
如果业务逻辑要求入参必须为Any类型,可以在运行时通过实例类型动态获取序列化器,注意该方案要求所有传入的实例所属类都已标记@Serializable:
import kotlinx.serialization.serializer import kotlin.reflect.full.starProjectedType class SerializerAdapter: SerializerPort { private val logger: Logger = LoggerFactory.getLogger(javaClass.simpleName) override fun toBase64(input: Any): String { return try { // 运行时获取实际类型对应的序列化器 val serializer = input::class.starProjectedType.serializer() val jsonString = Json.encodeToString(serializer, input) Base64.getEncoder().encodeToString(jsonString.toByteArray()) } catch (ex: Exception) { logger.error("[BASE64 Error] error converting json object to base64 encoded string: ${ex.stackTraceToString()}") "" } } }
该方案存在局限性:如果传入未标记
@Serializable的类型会抛出异常,且嵌套泛型场景下会因为类型擦除导致序列化失败。
内容的提问来源于stack exchange,提问作者Matias Barrios
相关产品推荐
相关产品推荐

