我在尝试将 Json 中传入的 REST-api 结果映射到对象时遇到以下错误:
failed to invoke private kotlinx.serialization.json.jsonelement() with no args
经过一些搜索,问题似乎是我试图实例化一个 Value() 对象,而它是一个密封类。 现在我不确定如何解决这个问题?
data class Device (
@SerializedName(value="DeviceSettings")
val deviceSettings: Map<String, Value>? = null,
@SerializedName(value="Id")
val id: String
)
sealed class Value {
class BoolValue(val value: Boolean) : Value()
class DoubleValue(val value: Double) : Value()
class IntegerValue(val value: Long) : Value()
class StringValue(val value: String) : Value()
}
问题出现在构造deviceSettings映射的时候。因为它可能包含多种类型的数据,所以定义了 Value 密封类。但正如所提到的,这只会在解析生物时崩溃......
想法是 DeviceSettings Map 是动态的,这就是为什么它实际上没有被解析为预定义数据类的原因!它可能包含一个键值对,但也可能有三十个!
@cutiko 没错,特此收到一些 json :
"DeviceSettings": {
"ToneLevel": 80.0,
"AutoLogging": false,
"OrientationLandscape": false,
"AudioDuration": 2500.0,
"ShoutLevel": 1.0,
"SipExtension": 0.0,
"SipServerAuthenticationKey": "",
"SipServerPort": 5060.0,
"SipServerUri": ""
}
您将必须编写自定义
TypeAdapter
来查看 JSON 数据的类型,并根据它选择正确的 Value
子类进行实例化。例如:
object ValueTypeAdapter : TypeAdapter<Value>() {
override fun write(writer: JsonWriter, value: Value?) {
throw UnsupportedOperationException()
}
override fun read(reader: JsonReader): Value {
return when (val token = reader.peek()) {
JsonToken.BOOLEAN -> Value.BoolValue(reader.nextBoolean())
JsonToken.STRING -> Value.StringValue(reader.nextString())
JsonToken.NUMBER -> {
// Read the string representation of the number
val numberAsStr = reader.nextString()
// If number contains decimal point or exponent prefix 'e', parse as Double
if (numberAsStr.any { c -> c == '.' || c == 'e' || c == 'E' }) {
Value.DoubleValue(numberAsStr.toDouble())
} else {
Value.IntegerValue(numberAsStr.toLong())
}
}
else -> throw IllegalArgumentException("Unexpected value type $token at ${reader.path}")
}
}
}
然后您可以像这样在
GsonBuilder
上注册适配器:
val gson = GsonBuilder()
.registerTypeAdapter(Value::class.java, ValueTypeAdapter)
.create()
然而,有几件事需要考虑,因此您可能需要调整此代码:
-0
?使用上面的代码,它将被解析为 Long
并且 -
符号将丢失。也许您想将其解析为 Double
-0.0
。Double
,还是您有不同的逻辑来决定什么是Double
或Long
?kotlinx.serialization
的联系尚不清楚。