首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用kotlinx.serialization忽略未知类型?

如何使用kotlinx.serialization忽略未知类型?
EN

Stack Overflow用户
提问于 2022-03-28 22:40:20
回答 1查看 629关注 0票数 2

我有几个类要反序列化,其中包括多态类型列表。我可以让它反序列化正确的已知类型,但是反序列化未知类型会引发异常。我真正想要的是,列表只包含已知类型,未知类型只是过滤掉。如果能以通用的方式做到这一点,那就更好了。

代码语言:javascript
复制
sealed interface BaseInterface

interface I1 : BaseInterface {
  fun f1(): String
}

interface I2: BaseInterface {
  fun f2(): String
}

@Serializable
@SerialName("i1")
data class I1Rest(value: String): I1 {
  fun f1(): String = value
}

@Serializable
@SerialName("i2")
data class I2Rest(value: String): I2 {
  fun f2(): String = value
}

@Serializable
data class SomeClass(list: List<BaseInterface>)

如何正确地反序列化SomeClass

代码语言:javascript
复制
{ "list": [ {"type": "i1", "value": "v1" }, {"type": "i2", "value": "v2" }, {"type": "i3", "value": "v3" } ] }

如果我不将i3类型添加到json中,则可以使用

代码语言:javascript
复制
SerializersModule {
  polymorphic(BaseInterface::class){
    subclass(I1Rest::class)
    subclass(I2Rest::class)
  }
}

但一旦我包括了一个未知类型,它就会破裂。请注意,我不希望将未知数反序列化为默认类型(必须扩展基本密封接口)。我想要的是忽略/过滤那些未知数。(最好是以泛型的方式),我还想将BaseInterface保留为接口而不是类,因为我只想公开接口,而不想公开具体的类(这是用于lib的)

EN

回答 1

Stack Overflow用户

发布于 2022-03-31 08:33:18

好吧,这是我能想到的最好的了:

代码语言:javascript
复制
@Serializable
data class SomeClass(
    @Serializable(with = UnknownBaseInterfaceTypeFilteringListSerializer::class)
    val list: List<BaseInterface>
)

val json = Json {
    ignoreUnknownKeys = true
    serializersModule = SerializersModule {
        polymorphic(BaseInterface::class) {
            subclass(I1Rest::class)
            subclass(I2Rest::class)
            defaultDeserializer { UnknownTypeSerializer() }
        }
    }
}

class FilteringListSerializer<E>(private val elementSerializer: KSerializer<E>) : KSerializer<List<E>> {
    private val listSerializer = ListSerializer(elementSerializer)
    override val descriptor: SerialDescriptor = listSerializer.descriptor

    override fun serialize(encoder: Encoder, value: List<E>) {
        listSerializer.serialize(encoder, value)
    }

    override fun deserialize(decoder: Decoder): List<E> = with(decoder as JsonDecoder) {
        decodeJsonElement().jsonArray.mapNotNull {
            try {
                json.decodeFromJsonElement(elementSerializer, it)
            } catch (e: UnknownTypeException) {
                null
            }
        }
    }
}

class UnknownTypeException(message: String) : SerializationException(message)

open class UnknownTypeSerializer<T> : KSerializer<T> {
    override val descriptor: SerialDescriptor = buildClassSerialDescriptor("Nothing")
    override fun deserialize(decoder: Decoder): T = throw UnknownTypeException("unknown type")
    override fun serialize(encoder: Encoder, value: T) = throw UnknownTypeException("unknown type")
}

object UnknownBaseInterfaceTypeFilteringListSerializer : KSerializer<List<BaseInterface>> by FilteringListSerializer(PolymorphicSerializer(BaseInterface::class))
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71654470

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档