Java
JSON
Deserialization
ArrayList
Jackson

Can not deserialize instance of java.util.ArrayList out of START_OBJECT token

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

This Jackson error means your Java target type expects a list, but the JSON payload starts as an object. In short, the structure of your class does not match the structure of incoming JSON. The fix is to map the root shape correctly and deserialize into the right type.

What the Error Message Actually Tells You

The phrase out of START_OBJECT token indicates the parser saw object-start at root while your code asked for ArrayList or List<T> root.

Typical mismatch:

  • expected: JSON array root
  • received: JSON object root containing an array field

Array root example:

json
1[
2  {"id": 1, "name": "A"},
3  {"id": 2, "name": "B"}
4]

Object root example:

json
1{
2  "items": [
3    {"id": 1, "name": "A"}
4  ],
5  "total": 1
6}

These require different Java target types.

Correct Mapping for Array Root

When payload root is an array, deserialize with TypeReference<List<Item>>.

java
1import com.fasterxml.jackson.core.type.TypeReference;
2import com.fasterxml.jackson.databind.ObjectMapper;
3import java.util.List;
4
5class Item {
6    public int id;
7    public String name;
8}
9
10ObjectMapper mapper = new ObjectMapper();
11String json = "[{\"id\":1,\"name\":\"A\"},{\"id\":2,\"name\":\"B\"}]";
12
13List<Item> items = mapper.readValue(json, new TypeReference<List<Item>>() {});
14System.out.println(items.size());

This succeeds because root type and Java target type align.

Correct Mapping for Object Wrapper Root

When payload root is object wrapper, create DTO for wrapper and deserialize into it.

java
1import java.util.List;
2
3class Payload {
4    public List<Item> items;
5    public int total;
6}
7
8String wrapped = "{\"items\":[{\"id\":1,\"name\":\"A\"}],\"total\":1}";
9Payload payload = mapper.readValue(wrapped, Payload.class);
10System.out.println(payload.items.get(0).name);

Do not deserialize wrapped payload directly to list.

Typical API Integration Pattern

Many APIs return metadata and data together. Examples include page index, total count, cursor, and items list. In those APIs, list-only mapping is incorrect even if items field exists.

A robust response model usually includes:

  • metadata fields
  • list payload field
  • optional error fields

Modeling full contract improves resilience when API evolves.

If endpoint versions differ, keep separate DTOs per version rather than one mutable class with optional fields for every era.

Debugging Workflow When Error Appears

A practical diagnosis sequence:

  1. capture raw JSON at integration boundary.
  2. inspect root token type quickly.
  3. compare with current target class.
  4. adjust DTO shape or endpoint parser route.

For quick root-token check, you can parse tree first:

java
1import com.fasterxml.jackson.databind.JsonNode;
2
3JsonNode node = mapper.readTree(rawJson);
4if (node.isArray()) {
5    System.out.println("array root");
6} else if (node.isObject()) {
7    System.out.println("object root");
8}

This helps when contracts are unclear or provider docs are outdated.

Hardening Against Contract Drift

To avoid runtime surprises in production:

  • keep fixture JSON samples in tests
  • validate root shape in integration tests
  • pin client parsing logic to endpoint version
  • fail fast with explicit parser errors

Avoid broad catch blocks that silently fallback to generic maps. They hide schema problems and create delayed failures downstream.

If payload field names differ from Java naming conventions, use @JsonProperty explicitly instead of relying on implicit naming assumptions.

Common Pitfalls

Deserializing object-root payload directly into list type causes immediate token mismatch errors.

Assuming all endpoints return same root shape leads to fragile shared parsing helpers.

Using untyped List<Object> or raw maps for core domain paths makes validation weak and maintenance harder.

Ignoring parser error details wastes debugging time because the message already indicates root mismatch.

Summary

  • This error is usually a root JSON shape mismatch, not a Jackson bug.
  • Match Java target type to actual payload root token.
  • Use TypeReference<List<T>> only for array-root payloads.
  • Use wrapper DTOs for object-root payloads with nested lists.
  • Add contract-shape tests to catch API drift before runtime failures.

Course illustration
Course illustration

All Rights Reserved.