当前位置:  开发笔记 > 前端 > 正文

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

如何解决《使用Gson和Kotlin1.0beta4反序列化具有延迟属性的类》经验,为你挑选了2个好方法。

使用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":{}),但这不是我想要的,因为它是从其他属性计算的.我想如果我找到一种方法来阻止该属性被序列化,那么将会修复反序列化崩溃.



1> Fabian Zeind..:

由于Kotlin 1.0只是标记这样的字段在de/serialization期间忽略它:

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


我(仍然)得到这个:`java.lang.NullPointerException:尝试在空对象引用`上调用接口方法'java.lang.Object kotlin.Lazy.getValue()'.使用非惰性(计算)变量有效.

2> Sergey Mashk..:

原因是该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

推荐阅读
手机用户2402851335
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有