Gson与Kotlin嵌套类

时间:2017-06-10 10:41:21

标签: gson deserialization kotlin

我无法正确地将嵌套的Kotlin类反序列化为Gson的正确类型。 当我尝试反序列化相同的Java类时,它工作正常。

Java类:

package example;

import java.util.List;
import java.util.Map;

class TestJsonJava {
    Map<String, List<Entry>> outer;

    static class Entry {
        String inner;
    }
}

Kotlin课程:

package example

class TestJsonKotlin {
    var outer: Map<String, List<Entry>>? = null

    class Entry {
        var inner: String? = null
    }
}

Kotlin主要:

package example

import com.google.gson.GsonBuilder

class Main {
    companion object {
        @JvmStatic
        fun main(args: Array<String>) {
            val json = """
{
    "outer": {
        "keyA": [
            {
                "inner": "hello"
            }
        ]
    }
}
"""
            val javaObject = GsonBuilder().create().fromJson(json, TestJsonJava::class.java)
            val javaWorks = javaObject.outer!!["keyA"]!![0] is TestJsonJava.Entry
            println("Java works  : $javaWorks")
            println(javaObject.outer!!["keyA"]!![0].inner)

            val kotlinObject = GsonBuilder().create().fromJson(json, TestJsonKotlin::class.java)
            val kotlinWorks = kotlinObject.outer!!["keyA"]!![0] is TestJsonKotlin.Entry
            println("Kotlin works: $kotlinWorks")
            println(kotlinObject.outer!!["keyA"]!![0].inner)
        }
    }
}

打印:

Java works  : true
hello
Kotlin works: false
Exception in thread "main" java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to example.TestJsonKotlin$Entry
    at example.Main$Companion.main(TestJsonmain.kt:28)
    at example.Main.main(TestJsonmain.kt)

如何告诉gson将keyA的值反序列化为List<Entry>而不是LinkedTreeMap

1 个答案:

答案 0 :(得分:4)

使用List注释@JvmSuppressWildcards似乎有所帮助:

var outer: Map<String, @JvmSuppressWildcards List<Entry>>? = null

如果我们不使用@JvmSuppressWildcards,那么Kotlin代码将转换为:

Map<String, ? extends List<TestJsonKotlin.Entry>> outer;

如果我们使用它,那么代码将转换为:

Map<String, List<TestJsonKotlin.Entry>> outer;

区别在于通配符? extends - 即使您用Java编写它也不支持。我在Gson的存储库here中提交了一个问题。

javap突出显示两种情况之间的区别:

// `TestJsonKotlin` with `val outer` is compiled to
public final class TestJsonKotlin {
  private final java.util.Map<java.lang.String, java.util.List<TestJsonKotlin$Entry>> outer;
  public final java.util.Map<java.lang.String, java.util.List<TestJsonKotlin$Entry>> getOuter();
  // ...
}

// `TestJsonKotlin` with `var outer` is compiled to
public final class TestJsonKotlin {
  private java.util.Map<java.lang.String, ? extends java.util.List<TestJsonKotlin$Entry>> outer;
  public final java.util.Map<java.lang.String, java.util.List<TestJsonKotlin$Entry>> getOuter();
  // ...
}

var案例会在? extends前面添加java.util.List<TestJsonKotlin$Entry>