1. 概述
在本簡短教程中,我們將闡明如何修復異常 JsonMappingException: 無法從 Object 值(令牌 `JsonToken.START_OBJECT`)中反序列化 java.util.ArrayList 實例。
首先,我們將突出顯示異常的主要原因。然後,我們將演示如何在實踐中重現它,最後,我們將解決它。
2. 理解異常
通常,Jackson 會拋出 JsonMappingException 以指示在反序列化 JSON 字符串時發生的致命映射錯誤。因此,堆棧跟蹤 "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 失敗時會產生“Cannot deserialize value of type `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 實例的原因。然後,我們展示瞭如何產生該異常,以及如何解決它。