使用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跳过它.使用beta 4,这是不可能的,因为注释会导致编译错误.
This annotation is not applicable to target 'member property without backing field'
我无法弄清楚如何解决这个问题.有任何想法吗?
编辑:lazy属性被序列化为JSON("my_lazy_prop$delegate":{}
),但这不是我想要的,因为它是从其他属性计算的.我想如果我找到一种方法来阻止该属性被序列化,那么将会修复反序列化崩溃.
由于Kotlin 1.0只是标记这样的字段在de/serialization期间忽略它:
@delegate:Transient val field by lazy { ... }
原因是该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>, JsonDeserializer > { 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 (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) { 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(c.f) }
这将产生以下输出:
{"f":1,"o":0} C(o=0) 1