使用Gson和Kotlin 1.0 beta 4反序列化具有惰性属性的类

使用Gson,我想反序列化一个包含懒惰属性的Kotlin类。

Kotlin 1.0 beta 4在对象反序列化过程中出现以下错误:

Caused by: java.lang.InstantiationException: can't instantiate class kotlin.Lazy 

用Kotlin 1.0 beta 2,我用@Transient annotaiton来标记属性,告诉Gson跳过它。 随着测试版4,这是不可能的,因为注释导致编译错误。

 This annotation is not applicable to target 'member property without backing field' 

我无法弄清楚如何解决这个问题。 有任何想法吗?

编辑:懒惰属性序列化为JSON( "my_lazy_prop$delegate":{} ),但这不是我想要的,因为它是从其他属性计算。 我想,如果我找到一种方法来防止财产被序列化,反序列化崩溃将被修复。

原因是delegate字段实际上并不是一个支持字段,因此被禁止。 其中一个解决方法是实施ExclusionStrategy : https : //stackoverflow.com/a/27986860/1460833

类似的东西:

 @Retention(AnnotationRetention.RUNTIME) @Target(AnnotationTarget.FIELD, AnnotationTarget.PROPERTY) annotation class GsonTransient object TransientExclusionStrategy : ExclusionStrategy { override fun shouldSkipClass(type: Class<*>): Boolean = false override fun shouldSkipField(f: FieldAttributes): Boolean = f.getAnnotation(GsonTransient::class.java) != null || f.name.endsWith("\$delegate") } fun gson() = GsonBuilder() .setExclusionStrategies(TransientExclusionStrategy) .create() 

请参阅相关票https://youtrack.jetbrains.com/issue/KT-10502

另一个解决方法是序列化惰性值以及:

 object SDForLazy : JsonSerializer<Lazy<*>>, JsonDeserializer<Lazy<*>> { override fun serialize(src: Lazy<*>, typeOfSrc: Type, context: JsonSerializationContext): JsonElement = context.serialize(src.value) override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Lazy<*> = lazyOf<Any?>(context.deserialize(json, (typeOfT as ParameterizedType).actualTypeArguments[0])) } class KotlinNamingPolicy(val delegate: FieldNamingStrategy = FieldNamingPolicy.IDENTITY) : FieldNamingStrategy { override fun translateName(f: Field): String = delegate.translateName(f).removeSuffix("\$delegate") } 

用法示例:

 data class C(val o: Int) { val f by lazy { 1 } } fun main(args: Array<String>) { val gson = GsonBuilder() .registerTypeAdapter(Lazy::class.java, SDForLazy) .setFieldNamingStrategy(KotlinNamingPolicy()) .create() val s = gson.toJson(C(0)) println(s) val c = gson.fromJson(s, C::class.java) println(c) println(cf) } 

这将产生以下输出:

 {"f":1,"o":0} C(o=0) 1 

由于Kotlin 1.0只是将这个字段标记为de / serialization时忽略它:

 @delegate:Transient val field by lazy { ... }