"errorMsg": "JSON parse error: Cannot deserialize instance of `java.util.ArrayList` out of START_OBJECT token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.util.ArrayList` out of START_OBJECT token\n at [Source: (PushbackInputStream); line: 1, column: 1]"
时间: 2025-03-24 14:06:10 浏览: 49
### 解决方案
当遇到 `JSON parse error: Cannot deserialize instance of 'java.util.ArrayList' out of START_OBJECT token` 错误时,这通常是由于前端传递的 JSON 数据结构与后端期望的数据类型不一致引起的。以下是详细的分析和解决方案:
#### 1. **问题原因**
此错误的核心原因是 Jackson 序列化/反序列化工具试图将一个 JSON 对象 (`START_OBJECT`) 转换为 Java 的 `ArrayList` 类型,而这两种类型的结构并不兼容[^4]。
- 如果后端期待的是一个数组(即 JSON 中的 `[ ]`),但实际接收到的是单个对象(即 `{ }`),就会触发该错误。
- 前端可能发送了一个单独的对象而不是列表形式的数据。
#### 2. **解决方法**
##### 方法一:调整前端数据格式
如果前端确实应该传递一组数据,则需确保其以 JSON 数组的形式发送给服务器。例如:
```json
[
{
"id": 1,
"name": "Item A"
},
{
"id": 2,
"name": "Item B"
}
]
```
而非单一对象:
```json
{
"id": 1,
"name": "Item A"
}
```
通过修改前端代码来满足后端需求可以有效解决问题[^5]。
##### 方法二:更改后端参数定义
假如业务逻辑允许接收单个实体作为输入之一,在这种情况下可考虑改变控制器方法签名,使其能够接受更灵活的数据类型。比如改为支持接收单个 DTO 或者封装类包含 list 属性的方式处理请求体。
示例代码如下所示:
```java
@PostMapping("/example")
public ResponseEntity<?> handleRequest(@RequestBody DeliveryDTO deliveryDTO){
// Process the request...
}
// Or use wrapper class approach:
class WrapperClass {
private List<DeliveryDTO> deliveries;
public void setDeliveries(List<DeliveryDTO> deliveries) { this.deliveries = deliveries;}
public List<DeliveryDTO> getDeliveries() {return this.deliveries;}
}
```
上述方式提供了另一种途径去适配不同形态下的客户端提交内容[^3]。
##### 方法三:自定义 Deserializer
对于某些特殊场景下无法简单地依靠调整前后端交互协议达成目标的情况,还可以借助于 Jackson 提供的功能来自定义 deserialization 行为。创建一个新的 deserializer 并注册它至 ObjectMapper 实现特定规则下的转换过程[^1]。
具体实现步骤包括但不限于以下几个方面:
1. 定义新的 deserializer 子类继承 JsonDeserializer<T>;
2. Override deserialize 方法完成定制化的解析流程;
3. 使用 @JsonDeserialize(using=CustomDeserializer.class) 注解标注相应字段或者全局配置 objectmapper 添加此类实例。
#### 3. **注意事项**
无论采取哪种策略都需要仔细验证最终效果并测试边界条件以防引入新 bug 。另外也要注意保持 API 文档清晰准确以便维护人员理解接口预期行为[^2]。
---
### 示例代码片段
下面给出一段简单的例子展示如何设置自定义的 deserializers 来应对复杂情形:
```java
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
public class CustomListDeserializer extends StdDeserializer<List<MyObject>> {
protected CustomListDeserializer() {
super((Class<List<MyObject>>) null);
}
@Override
public List<MyObject> deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
ObjectMapper mapper = (ObjectMapper)jp.getCodec();
JsonNode node = mapper.readTree(jp);
if(node.isArray()){
return mapper.convertValue(node, new TypeReference<List<MyObject>>() {});
}else{
MyObject obj = mapper.treeToValue(node, MyObject.class);
return Collections.singletonList(obj);
}
}
}
```
随后可以在对应的 model 上应用这个 custom deserializer :
```java
@JsonDeserialize(using = CustomListDeserializer.class)
private List<MyObject> myObjects;
```
这样即使传来的 json 是 single object ,也能被正确解释成只有一个 element 的 list 结构。
---
阅读全文
相关推荐



















