簡體   English   中英

為什么 Gson 允許正常的數組聲明,然后在 Map 中訪問它時拋出 ClassCastException?

[英]Why does Gson allow normal array declaration, then throw ClassCastException when accessing it in a Map?

當使用Gson將 JSON 映射轉換為 Kotlin/Java 映射,並且 JSON 值包含數組為"[]" ,如果聲明Array<T>然后訪問將出現ClassCastException錯誤。 Array<T>等價於 Java 數組T[] ):

應用程序/build.gradle:

dependencies {
   ...
   implementation 'com.google.code.gson:gson:2.8.6'
}

JsonConverter.kt(使用本指南):

@Throws(JsonSyntaxException::class)
fun gsonMapTest() {
    val jsonInput = """
        {"keyOne":[],"keyTwo":["valueA"],"keyThree":[]}
    """.trimIndent()

    // Guidance: https://www.baeldung.com/gson-json-to-map
    val jsonMap1 = Gson().fromJson<LinkedTreeMap<String, Array<String>>>(jsonInput, MutableMap::class.java)
    val jsonMap2: Map<*,*> = Gson().fromJson(jsonInput, Map::class.java) // MutableMap can also be used

    // These work fine
    val firstKeyInMap1: String = jsonMap1.keys.first() // returns String
    val firstKeyInMap2 = jsonMap2.keys.first() // returns String

    // Errors here: "java.lang.ClassCastException: java.util.ArrayList cannot be cast to [Ljava.lang.String;"
    val firstValueInMap1: Array<String> = jsonMap1.values.first()
    val firstValueInMap2: Array<String> = jsonMap2.values.first() as Array<String>
}

此錯誤發生在運行時:

java.lang.ClassCastException: java.util.ArrayList cannot be cast to [Ljava.lang.String;

但是允許創建 Map 對象,沒有任何警告或錯誤。 只有在訪問 Map 值時才會發生錯誤。

從錯誤消息中,我最初認為對jsonMap1.values.first()的調用試圖將空數組轉換為字符串。 我最終發現錯誤消息中的"[L"表示“對象數組”

如果代碼示例中的聲明從Array<String>更改為ArrayList<String>則一切正常。

所以我的問題是:

  • Gson 允許Array<T>聲明是正常行為,但在訪問項目時會導致錯誤嗎?
  • 有沒有辦法顯示警告或編譯錯誤來說明應該使用ArrayList<String>而不是Array<String>

我檢查了 Gson 的 Github 問題。 我找不到報告的這個問題,但我發現了一些稍微相似的問題:

更新:也許這是同樣的問題?: Java gson, ClassCastException ondecode to Map<String,String[]>

正如用戶fluffy在他/她的評論中提到的,除了泛型聲明之外,還必須使用TypeToken來反序列化參數化泛型類型。 但是, ArrayList<String>似乎不需要它:

@Test
@Throws(JsonSyntaxException::class)
fun gsonMapTest() {
    val jsonInput = """
    {"keyOne":[],"keyTwo":["valueA"],"keyThree":[]}
    """.trimIndent()

    // Guidance: https://www.baeldung.com/gson-json-to-map
    val jsonMap1 = Gson().fromJson<LinkedTreeMap<String, ArrayList<String>>>(jsonInput, MutableMap::class.java)

    val listType = object : TypeToken<LinkedTreeMap<String, Array<String>>>() {}.type
    val jsonMap2: Map<*,*> = Gson().fromJson(jsonInput, listType) // MutableMap can also be used

    // These work fine
    val firstKeyInMap1: String = jsonMap1.keys.first() // returns String "keyOne"
    val firstKeyInMap2 = jsonMap2.keys.first() // returns String "keyOne"

    // No longer errors here
    val firstValueInMap1: ArrayList<String> = jsonMap1.values.first() // returns empty list
    val firstValueInMap2: Array<String> = jsonMap2.values.first() as Array<String> // returns empty array
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM