如何序列化/反序列化Kotlin密封类? [英] How to serialize/deserialize Kotlin sealed class?

查看:708
本文介绍了如何序列化/反序列化Kotlin密封类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下密封的类:

sealed class ViewModel {

  data class Loaded(val value : String) : ViewModel()
  object Loading : ViewModel()

}

我如何序列化/反序列化ViewModel类的实例,比方说JSON格式?

How can I serialize/deserialize instances of the ViewModel class, let's say to/from JSON format?

我尝试使用Genson序列化器/反序列化器库-它可以处理Kotlin数据类,还可以支持多态类型(例如,使用某些元数据指定具体的类型)。

I've tried to use Genson serializer/deserializer library - it can handle Kotlin data classes, it's also possible to support polymorphic types (eg. using some metadata to specify concrete types).

但是,库在Kotlin object 类型上失败,因为这些都是单例,没有公共构造函数。我想我可以编写一个自定义的Genson转换器来处理它,但是也许有更简单的方法可以做到这一点?

However, the library fails on Kotlin object types, as these are singletons without a public constructor. I guess I could write a custom Genson converter to handle it, but maybe there's an easier way to do it?

推荐答案

我结束了实施自定义Converter以及Factory以将其正确插入Genson。

I ended up implementing a custom Converter plus a Factory to properly plug it into Genson.

它使用Genson的元数据约定将对象表示为:

It uses Genson's metadata convention to represent the object as:

{ 
  "@class": "com.example.ViewModel.Loading" 
}

转换器假定设置了 useClassMetadata 标志,因此序列化只需要标记一个空对象即可。对于反序列化,它从元数据中解析类名称,将其加载并获取 objectInstance

The converter assumes useClassMetadata flag set, so serialization just needs to mark an empty object. For deserialization, it resolves class name from metadata, loads it and obtains objectInstance.

object KotlinObjectConverter : Converter<Any> {

override fun serialize(objectData: Any, writer: ObjectWriter, ctx: Context) {
    with(writer) {
        // just empty JSON object, class name will be automatically added as metadata
        beginObject()
        endObject()
    }
}

override fun deserialize(reader: ObjectReader, ctx: Context): Any? =
    Class.forName(reader.nextObjectMetadata().metadata("class"))
        .kotlin.objectInstance
        .also { reader.endObject() }
}

为确保此转换器仅应用于实际的对象,我对其进行了注册

To make sure that this converter is applied only to actual objects, I register it using a factory, that tells Genson when to use it and when to fall back to the default implementation.

object KotlinConverterFactory : Factory<Converter<Any>> {

    override fun create(type: Type, genson: Genson): Converter<Any>? =
        if (TypeUtil.getRawClass(type).kotlin.objectInstance != null) KotlinObjectConverter
        else null

}

工厂可用于通过构建器配置Genson:

The factory can be used to configure Genson via builder:

GensonBuilder()
        .withConverterFactory(KotlinConverterFactory)
        .useClassMetadata(true) // required to add metadata during serialization
        // some other properties
        .create()

使用链式转换器功能,代码可能会更好,但是我还没有时间检查它

The code probably could be even nicer with chained converters feature, but I didn't have time to check it out yet.

这篇关于如何序列化/反序列化Kotlin密封类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆