Cannot deserialize value of type X from Array value

ErrorJava

com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `com.example.Order` from Array value (token `JsonToken.START_ARRAY`)

What it means

The JSON starts with [, so it is a list, but you asked Jackson for one object. Read it as a List<Order> with a TypeReference, or get the sender to send one object.

Last verified on Jackson 2.21 and 3.1; Spring 6.2 and 7.0.

This JSON is valid. The problem is on the Java side, so a JSON validator would say it is fine.

Usually
A list read into one objectThe API started sending a listThe opposite: one object where you expected a listSpring does not say where
Fix
Read it as a list: List<Order> orders = mapper.readValue(json, new TypeReference<List<Order>>() {});.

The fix

Read it as a list: List<Order> orders = mapper.readValue(json, new TypeReference<List<Order>>() {});. If the API is supposed to send one order, fix the sender instead.

The JSON that was sent: request.jsonValid JSON
[
  { "id": 1, "status": "shipped" },
  { "id": 2, "status": "pending" }
]
A JSON validator says this is fine.
Broken.javaThrows
public class Order {
  public long id;
  public String status;
}

Order order = mapper.readValue(json, Order.class);
Throws MismatchedInputException

Line 6 changes.

Fixed.javaWorks
public class Order {
  public long id;
  public String status;
}

List<Order> orders = mapper.readValue(json, new TypeReference<List<Order>>() {});
Reads without an error.

How the message appears

Jackson 2, then Jackson 3, then Spring (the same on 6.2 and 7.0). The last line is the opposite mistake: one object read into a List.

Console
  • com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `com.example.Order` from Array value (token `JsonToken.START_ARRAY`)
  • at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); line: 1, column: 1]
  • tools.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `com.example.Order` from Array value (token `JsonToken.START_ARRAY`)
  • at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); byte offset: #UNKNOWN]
  • org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `com.example.Order` from Array value (token `JsonToken.START_ARRAY`)
  • Cannot deserialize value of type `java.util.ArrayList<com.example.Order>` from Object value (token `JsonToken.START_OBJECT`)

What causes it

  1. A list read into one object

    Look at the first character of the JSON. [ is a list and { is one object. Here it is [, and Order.class asks for one object. Jackson tells you both: the type you asked for, and the token it found, JsonToken.START_ARRAY.

  2. The API started sending a list

    Code written for one record breaks when the other side starts sending several. The JSON is still valid, so nothing looks wrong until you read it. Check what the API says it returns.

  3. The opposite: one object where you expected a list

    Read a single object into List<Order> and you get the same message the other way round: from Object value and JsonToken.START_OBJECT. The type shows as java.util.ArrayList<com.example.Order>.

  4. Spring does not say where

    Spring wraps it as JSON parse error: Cannot deserialize value of type, then the type and from Array value, without the at [Source: ...] line. The type in the message is the type of your request body. Other Spring messages are on the Spring page.

Your JSON and text are processed entirely in your browser and are never sent anywhere. To understand how the site is used we record each page view (the page, the referrer and an approximate location from your IP address) and keep it for 90 days. Nothing is stored on your device unless you choose it. Accept to also store a device identifier here and record your browser and device characteristics, which is what lets a return visit be told from a new one. Decline and nothing is sent at all. We respect Do Not Track. See our privacy policy.