如何序列化/反序列化Kotlin密封类? [英] How to serialize/deserialize Kotlin sealed class?
问题描述
我有以下密封的类:
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屋!