1. 概述
本教程將介紹如何解決異常 <em >JsonMappingException: Can not deserialize instance of java.util.ArrayList from Object value (tokenJsonToken.START_OBJECT`)。
首先,我們將重點分析導致該異常的主要原因。然後,我們將演示如何在實踐中重現該異常,最後,我們將展示如何解決它。
2. 理解異常
通常,Jackson 在反序列化 JSON 字符串時會拋出 <em>JsonMappingException</em> 以指示致命的映射錯誤。因此,堆棧跟蹤“Can not deserialize instance of java.util.ArrayList”表明 Jackson 無法將 JSON 屬性映射到 ArrayList 實例。
簡而言之,導致此異常的最常見原因是在使用花括號 "…" 來表示集合,而不是方括號 "…"。
3. 重新觸發異常
現在我們知道 Jackson 拋出 JsonMappingException 的原因,接下來讓我們通過一個實際示例來演示如何重現它。
讓我們考慮 Country 類:
public class Country {
private String name;
private List<String> cities;
// standard getters and setters
}
如我們所見,一個國家由名稱和城市列表定義。
接下來,讓我們假定使用花括號來在 JSON 字符串中定義城市:
{
"name": "Netherlands",
"cities": {"Amsterdam", "Tamassint"}
}現在嘗試將 JSON 字符串反序列化為 Country 類型的對象,將會產生以下結果:
Cannot deserialize value of type `java.util.ArrayList<java.lang.String>` from Object value (token `JsonToken.START_OBJECT`)
at [Source: (String)"{"name":"Netherlands","cities":{"Amsterdam", "Tamassint"}}"; line: 1, column: 32]
(through reference chain: com.baeldung.mappingexception.Country["cities"])
...最後,我們將創建一個測試用例以確認這一點:
@Test
public final void givenJsonWithInvalidList_whenDeserializing_thenThrowException() throws JsonParseException, IOException {
String json = "{\"name\":\"Netherlands\",\"cities\":{\"Amsterdam\", \"Tamassint\"}}";
ObjectMapper mapper = new ObjectMapper();
Exception exception = assertThrows(JsonMappingException.class, () -> mapper.reader()
.forType(Country.class)
.readValue(json));
assertTrue(exception.getMessage()
.contains("Cannot deserialize value of type `java.util.ArrayList<java.lang.String>`"));
}如上所示,Jackson 失敗原因是出現了“無法反序列化 java.util.ArrayList<java.lang.String> 類型的值”。
主要原因是我們在使用花括號來表示城市列表。對於 Jackson,{"Amsterdam", "Tamassint"} 不是有效的 JSON 數組。
4. 修復異常
最簡單的方法是使用方括號而不是花括號來定義元素的集合。 因此,為了解決此異常,首先需要修復我們的JSON字符串:
{
"name": "Netherlands",
"cities": ["Amsterdam", "Tamassint"]
}現在讓我們使用一個測試用例來驗證一切都按預期工作:
@Test
public final void givenJsonWithValidList_whenDeserializing_thenCorrect() throws JsonParseException, IOException {
String json = "{\"name\":\"Netherlands\",\"cities\":[\"Amsterdam\", \"Tamassint\"]}";
ObjectMapper mapper = new ObjectMapper();
Country country = mapper.reader()
.forType(Country.class)
.readValue(json);
assertEquals("Netherlands", country.getName());
assertEquals(Arrays.asList("Amsterdam", "Tamassint"), country.getCities());
}如我們所見,新的 JSON 字符串已成功地反序列化為 Country 對象。
5. 結論
在本文中,我們討論了導致JsonMappingException: 無法從 Object 值(token JsonToken.START_OBJECT)中反序列化 java.util.ArrayList 實例 的主要原因。 此外,我們展示瞭如何產生該異常以及如何解決它。