Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用Kotlin序列化为嵌套JSON组合多态序列化程序和转换序列化程序?_Kotlin - Fatal编程技术网

如何使用Kotlin序列化为嵌套JSON组合多态序列化程序和转换序列化程序?

如何使用Kotlin序列化为嵌套JSON组合多态序列化程序和转换序列化程序?,kotlin,Kotlin,这是我想要使用的JSON的一个简化示例: { “无用信息”:“无用信息”, “数据”:{ “无用信息2”:“无用信息2”, “儿童”:[ { “种类”:“汽车”, “数据”:{ “id”:1, “变速器”:“手动” } }, { “种类”:“船”, “数据”:{ “id”:2, “isDocked”:真 } } ] } } 子对象是车辆对象的数组车辆可以是船或汽车 我的问题 我想要的信息嵌套得很深(真正的JSON嵌套得很深)。一个hack解决方案是通过编写几十个相互引用的嵌套数据类来精确地建模

这是我想要使用的JSON的一个简化示例:

{
“无用信息”:“无用信息”,
“数据”:{
“无用信息2”:“无用信息2”,
“儿童”:[
{
“种类”:“汽车”,
“数据”:{
“id”:1,
“变速器”:“手动”
}
},
{
“种类”:“船”,
“数据”:{
“id”:2,
“isDocked”:真
}
}
]
}
}
子对象
车辆
对象的数组<代码>车辆可以是
汽车

我的问题 我想要的信息嵌套得很深(真正的JSON嵌套得很深)。一个hack解决方案是通过编写几十个相互引用的嵌套数据类来精确地建模JSON。我不想这样做

我的问题是,虽然我知道如何使用
JsonTransformingSerializer
来展开单个类型的数组,以及如何使用
jsonContentPolymorphicsSerializer
来处理各种类型的对象,但在这种情况下,我相信我需要两者,但我无法让它工作

我所做的 假设单一类型 我试着理解如果它是一种单一的类型,它将如何工作

如果我想要的对象都是同一类型的,那么实现一个
JsonTransformingSerializer
直接切入我想要的数据就很简单了。在本例中,我将假设我只关心ID,因此我可以创建一个通用的
车辆
模型

@Serializable
数据类车辆响应(
@可序列化(with=VehiclerResponseSerializer::class)
@序列名(“数据”)
val车辆:列表
)
@可序列化
数据类车辆(val id:Int)
对象VehiclerResponseSerializer:JsonTransformingSerializer(ListSerializer(Vehicle.serializer())){
重写反序列化(元素:JsonElement):JsonElement{
val车辆=mutableListOf()
//等于:[{“种类”:“汽车”,“数据”:{“id”:1,“变速器”:“手动”},{“种类”:“船”,“数据”:{“id”:2,“isDocked”:true}]
val vehicleArray=element.jsonObject[“children”]!!.jsonArray
vehicleArray.forEach{vehicle->
//等于:{“id”:1,“变速器”:“手动”}
val vehicleData=vehicle.jsonObject[“数据”]!!
车辆.添加(车辆数据)
}
返回JsonArray(vehicles.toList())
}
}
代码工作得很好。从main调用它,打印结果会给我:

VehicleResponse(vehicles=[Vehicle(id=1), Vehicle(id=2)])
但它们实际上是多态的! 假设一种类型不起作用。我需要使用
Car
Boat
,并调用它们各自的函数和属性

我试图对结构进行如下建模:

@Serializable
数据类车辆响应(
@可序列化(with=VehiclerResponseSerializer::class)
@序列名(“数据”)
val车辆:列表
)
@可序列化
抽象类车辆{
抽象值id:Int
}
@可序列化
数据级汽车(
覆盖值id:Int,
val传输:字符串,
):车辆()
@可序列化
数据级船(
覆盖值id:Int,
val isDocked:布尔值,
):车辆()
我想要什么
  • 我希望从服务器接收JSON,并立即能够将其反序列化为
    Vehicle
    对象列表,就像
    vehiclerresponse
    所拥有的那样

  • 我想浏览一个深度嵌套的JSON,并打开一个包含各种
    Vehicle
    对象的数组。为此,我假设需要使用
    JsonTransformingSerializer

  • 我想使用多态反序列化将
    Vehicle
    中的每一个转换为相应的子类型

实际问题 真正让我陷入困境的是多态序列化程序似乎并不适合。在我解析JSON之前先调用它。我应该如何决定使用哪个序列化程序

下面是一个测试实现:

对象VehiclePolymorphicSerializer:JsonContentPolymorphicSerializer(VehiclerResponse::class){
重写反序列化器(元素:JsonElement):反序列化策略{
println(“\n选择反序列化程序()\n”+
“基本元素:\n”+
“$element\n”)
//这个返回是一个临时的hack,我只想通过将其打印到控制台来查看基本元素
return vehiclerResponse.serializer()
}
}
它打印:

selectDeserializer()
base element:
{"useless_info":"useless info","data":{"useless_info2":"useless info 2","children":[{"kind":"Car","data":{"id":1,"transmission":"manual"}},{"kind":"Boat","data":{"id":2,"isDocked":true}}]}}
这就是最初的全部JSON!如果
Car
Boat
都在那里,我应该如何决定使用哪种反序列化策略?
JsonTransformingSerializer
jsonContentPolymorphicsSerializer
之后调用


我真的不知道我该怎么做。即使是一个小小的提示也非常感谢。

kotlinx.serialization
在这种情况下可以处理多态反序列化,而无需定制
jsonContentPolymorphicsSerializer
。您只需要在从
JsonTransformingSerializer
返回的JSON中保留:

object VehicleResponseSerializer : JsonTransformingSerializer<List<Vehicle>>(ListSerializer(Vehicle.serializer())) {
    override fun transformDeserialize(element: JsonElement): JsonElement {
        // equals: [{"kind":"Car","data":{"id":1,"totalWheels":"4"}},{"kind":"Boat","data":{"id":2,"isDocked":true}}]
        val vehicleArray = element.jsonObject["children"]!!.jsonArray

        // equals: [{"id":1,"totalWheels":"4"}, {"id":2,"isDocked":true}] // Note that class discriminator is absent here!
        return JsonArray(vehicleArray.map { it.jsonObject["data"]!! })
    }
}
对象VehiclerResponseSerializer:JsonTransformingSerializer(ListSerializer(Vehicle.serializer())){ 重写反序列化(元素:JsonElement):JsonElement{ //等于:[{“种类”:“汽车”,“数据”:{“id”:1,“totalWheels”:“4”},{“种类”:“船”,“数据”:{“id”:2,“isDocked”:true}] val vehicleArray=element.jsonObject[“children”]!!.jsonArray //等于:[{“类型”:“汽车”,“id”:1,“totalWheels”:“4”},{“类型”:“船”,“id”:2,“isDocked”:true}] 返回JsonArray(vehiclarray.map{ val data=it.jsonObject[“数据”]!!.jsonObject val type=it.jsonObject[“种类”]!! JsonObject( data.toMutableMap().apply{this[“type”]=type} /*
val kotlinx = Json {
    ignoreUnknownKeys = true
    serializersModule = module
}
object VehicleResponseSerializer : JsonTransformingSerializer<List<Vehicle>>(ListSerializer(Vehicle.serializer())) {
    override fun transformDeserialize(element: JsonElement): JsonElement {
        // equals: [{"kind":"Car","data":{"id":1,"totalWheels":"4"}},{"kind":"Boat","data":{"id":2,"isDocked":true}}]
        val vehicleArray = element.jsonObject["children"]!!.jsonArray

        // equals: [{"id":1,"totalWheels":"4"}, {"id":2,"isDocked":true}] // Note that class discriminator is absent here!
        return JsonArray(vehicleArray.map { it.jsonObject["data"]!! })
    }
}
object VehiclePolymorphicSerializer : JsonContentPolymorphicSerializer<Vehicle>(Vehicle::class) {
    override fun selectDeserializer(element: JsonElement): DeserializationStrategy<out Vehicle> = when {
        "isDocked" in element.jsonObject -> Boat.serializer()
        else -> Car.serializer()
    }
}
val module = SerializersModule {
    polymorphicDefault(Vehicle::class) { VehiclePolymorphicSerializer }
}

val kotlinx = Json {
    ignoreUnknownKeys = true
    serializersModule = module
}