Gson与Kotlin嵌套类

nio*_*ode 5 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

Kotlin类:

package example

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

    class Entry {
        var inner: String? = null
    }
}
Run Code Online (Sandbox Code Playgroud)

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)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这打印:

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)
Run Code Online (Sandbox Code Playgroud)

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

Ego*_*uba 4

注释List@JvmSuppressWildcards有帮助:

\n\n
var outer: Map<String, @JvmSuppressWildcards List<Entry>>? = null\n
Run Code Online (Sandbox Code Playgroud)\n\n
\n\n

如果我们不使用@JvmSuppressWildcards,那么 Kotlin 代码将被翻译为:

\n\n
Map<String, ? extends List<TestJsonKotlin.Entry>> outer;\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果我们确实使用它,那么代码将被翻译为:

\n\n
Map<String, List<TestJsonKotlin.Entry>> outer;\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n
\n\n

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

\n\n
// `TestJsonKotlin` with `val outer` is compiled to\npublic final class TestJsonKotlin {\n  private final java.util.Map<java.lang.String, java.util.List<TestJsonKotlin$Entry>> outer;\n  public final java.util.Map<java.lang.String, java.util.List<TestJsonKotlin$Entry>> getOuter();\n  // ...\n}\n\n// `TestJsonKotlin` with `var outer` is compiled to\npublic final class TestJsonKotlin {\n  private java.util.Map<java.lang.String, ? extends java.util.List<TestJsonKotlin$Entry>> outer;\n  public final java.util.Map<java.lang.String, java.util.List<TestJsonKotlin$Entry>> getOuter();\n  // ...\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

该案例在前面var添加? extendsjava.util.List<TestJsonKotlin$Entry>

\n