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

I ran into this same problem these days and maybe some more detail might be helpful to somebody else.

I was looking some security guidelines for REST APIs and crossed a very intriguing issue with json arrays. Check the link for details, but basically, you should wrap them within an Object as we already saw in this post question.

So, instead of:

  [
    {
      "name": "order1"
    },
    {
      "name": "order2"
    }
  ]

It's advisable that we always do:

  {
    "data": [
      {
        "name": "order1"
      },
      {
        "name": "order2"
      }
    ]
  }

This is pretty straight-forward when you doing a GET, but might give you some trouble if, instead, your trying to POST/PUT the very same json.

In my case, I had more than one GET that was a List and more than one POST/PUT that would receive the very same json.

So what I end up doing was to use a very simple Wrapper object for a List:

public class Wrapper<T> {
  private List<T> data;

  public Wrapper() {}

  public Wrapper(List<T> data) {
    this.data = data;
  }
  public List<T> getData() {
    return data;
  }
  public void setData(List<T> data) {
    this.data = data;
  }
}

Serialization of my lists were made with a @ControllerAdvice:

@ControllerAdvice
public class JSONResponseWrapper implements ResponseBodyAdvice<Object> {

  @Override
  public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
    return true;
  }

  @Override
  @SuppressWarnings("unchecked")
  public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
    if (body instanceof List) {
      return new Wrapper<>((List<Object>) body);
    }
    else if (body instanceof Map) {
      return Collections.singletonMap("data", body);
    }  
    return body;
  }
}

So, all the Lists and Maps where wrapped over a data object as below:

  {
    "data": [
      {...}
    ]
  }

Deserialization was still default, just using de Wrapper Object:

@PostMapping("/resource")
public ResponseEntity<Void> setResources(@RequestBody Wrapper<ResourceDTO> wrappedResources) {
  List<ResourceDTO> resources = wrappedResources.getData();
  // your code here
  return ResponseEntity
           .ok()
           .build();
}

That was it! Hope it helps someone.

Note: tested with SpringBoot 1.5.5.RELEASE.

Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to spring

Are all Spring Framework Java Configuration injection examples buggy? Two Page Login with Spring Security 3.2.x Access blocked by CORS policy: Response to preflight request doesn't pass access control check Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean Failed to auto-configure a DataSource: 'spring.datasource.url' is not specified Spring Data JPA findOne() change to Optional how to use this? After Spring Boot 2.0 migration: jdbcUrl is required with driverClassName The type WebMvcConfigurerAdapter is deprecated No converter found capable of converting from type to type

Examples related to jackson

No Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator JSON parse error: Can not construct instance of java.time.LocalDate: no String-argument constructor/factory method to deserialize from String value How to convert JSON string into List of Java object? Deserialize Java 8 LocalDateTime with JacksonMapper java.lang.IllegalArgumentException: No converter found for return value of type java.lang.ClassNotFoundException: com.fasterxml.jackson.annotation.JsonInclude$Value How to modify JsonNode in Java? Deserialize JSON with Jackson into Polymorphic Types - A Complete Example is giving me a compile error Convert Map to JSON using Jackson Required request body content is missing: org.springframework.web.method.HandlerMethod$HandlerMethodParameter

Examples related to jax-rs

Java 8 LocalDate Jackson format File upload along with other object in Jersey restful web service Best practice for REST token-based authentication with JAX-RS and Jersey MessageBodyWriter not found for media type=application/json Can not deserialize instance of java.util.ArrayList out of START_OBJECT token Read response body in JAX-RS client from a post request What is the difference between JAX-RS and JAX-WS? javax.xml.bind.JAXBException: Class *** nor any of its super class is known to this context When to use @QueryParam vs @PathParam How to set up JAX-RS Application using annotations only (no web.xml)?

Examples related to resteasy

No 'Access-Control-Allow-Origin' header is present on the requested resource - Resteasy Java 8 LocalDate Jackson format Can not deserialize instance of java.util.ArrayList out of START_OBJECT token REST - HTTP Post Multipart with JSON PersistenceContext EntityManager injection NullPointerException