使用Gson映射Kotlin密封类时遭遇实例化错误求助
解决Kotlinx Serialization解析密封类到动态Map的崩溃问题
你遇到的错误failed to invoke private kotlinx.serialization.json.jsonelement() with no args,本质是kotlinx.serialization默认无法将JSON中的基本类型(布尔、数字、字符串)直接映射到密封类Value的子类——因为密封类本身没有无参构造,且默认序列化逻辑需要额外类型标识(比如type字段),但你的JSON结构里只有纯基本类型值,没有类型信息。
解决方案
给密封类Value实现自定义序列化器,让序列化框架能根据JSON元素的类型自动匹配对应的Value子类。
完整代码实现
import kotlinx.serialization.* import kotlinx.serialization.json.* @Serializable data class Device ( @SerializedName("DeviceSettings") val deviceSettings: Map<String, Value>? = null, @SerializedName("Id") val id: String ) @Serializable(with = ValueSerializer::class) sealed class Value { data class BoolValue(val value: Boolean) : Value() data class DoubleValue(val value: Double) : Value() data class IntegerValue(val value: Long) : Value() data class StringValue(val value: String) : Value() } object ValueSerializer : KSerializer<Value> { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Value", PrimitiveKind.STRING) override fun serialize(encoder: Encoder, value: Value) { val jsonEncoder = encoder as JsonEncoder val jsonElement = when (value) { is Value.BoolValue -> JsonPrimitive(value.value) is Value.DoubleValue -> JsonPrimitive(value.value) is Value.IntegerValue -> JsonPrimitive(value.value) is Value.StringValue -> JsonPrimitive(value.value) } jsonEncoder.encodeJsonElement(jsonElement) } override fun deserialize(decoder: Decoder): Value { val jsonDecoder = decoder as JsonDecoder val jsonElement = jsonDecoder.decodeJsonElement() return when (jsonElement) { is JsonPrimitive -> { when { jsonElement.isBoolean -> Value.BoolValue(jsonElement.boolean) jsonElement.isString -> Value.StringValue(jsonElement.content) jsonElement.isNumber -> { val number = jsonElement.double // 适配JSON中如5060.0这类整数形式的浮点数 if (number == number.toLong().toDouble()) { Value.IntegerValue(number.toLong()) } else { Value.DoubleValue(number) } } else -> throw SerializationException("不支持的JsonPrimitive类型") } } else -> throw SerializationException("仅支持JsonPrimitive类型作为Value") } } }
关键细节说明
- 给
Value密封类添加@Serializable(with = ValueSerializer::class)注解,指定使用自定义序列化器处理该类的序列化/反序列化逻辑。 - 序列化器核心逻辑:
- 序列化:将
Value的各个子类实例转换为对应的JsonPrimitive类型(布尔、数字、字符串)。 - 反序列化:根据
JsonPrimitive的类型自动创建对应的Value子类实例;针对数字额外判断是否为整数,避免把5060.0这类值错误识别为浮点数。
- 序列化:将
使用示例
// 解析示例JSON val jsonContent = """ { "DeviceSettings": { "ToneLevel": 80.0, "AutoLogging": false, "OrientationLandscape": false, "AudioDuration": 2500.0, "ShoutLevel": 1.0, "SipExtension": 0.0, "SipServerAuthenticationKey": "", "SipServerPort": 5060.0, "SipServerUri": "" }, "Id": "device_001" } """ val device = Json.decodeFromString<Device>(jsonContent)
内容的提问来源于stack exchange,提问作者TiGer
相关产品推荐
相关产品推荐

