Gson与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
?
使用@JvmSuppressWildcards
注释List
似乎有助于:
var outer: Map<String, @JvmSuppressWildcards List<Entry>>? = null
如果我们不使用@JvmSuppressWildcards
,那么Kotlin代码被转换为:
Map<String, ? extends List<TestJsonKotlin.Entry>> outer;
如果我们使用它,那么代码被翻译成:
Map<String, List<TestJsonKotlin.Entry>> outer;
区别在于通配符? extends
? extends
– 即使用Java编写,也不支持。 我在这里提交了一个Gson仓库的问题 。
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
case添加? extends
在java.util.List<TestJsonKotlin$Entry>
? extends
。