util objetos metodo libreria imprimir importar guardar datos añadir java spring jackson jax-rs resteasy

objetos - metodo añadir en java



No se puede deserializar la instancia de java.util.ArrayList fuera del token START_OBJECT (4)

Estoy tratando de PUBLICAR una List de objetos personalizados. Mi JSON en el cuerpo de la solicitud es este:

{ "collection": [ { "name": "Test order1", "detail": "ahk ks" }, { "name": "Test order2", "detail": "Fisteku" } ] }

Código del lado del servidor que maneja la solicitud:

import java.util.Collection; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; @Path(value = "/rest/corder") public class COrderRestService { @POST @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON) public Response postOrder(Collection<COrder> orders) { StringBuilder stringBuilder = new StringBuilder(); for (COrder c : orders) { stringBuilder.append(c.toString()); } System.out.println(stringBuilder); return Response.ok(stringBuilder, MediaType.APPLICATION_JSON).build(); } }

Entidad COrder :

import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement public class COrder { String name; String detail; @Override public String toString() { return "COrder [name=" + name + ", detail=" + detail + ", getClass()=" + getClass() + ", hashCode()=" + hashCode() + ", toString()=" + super.toString() + "]"; } }

Pero se lanza una excepción:

SEVERE: Failed executing POST /rest/corder org.jboss.resteasy.spi.ReaderException: org.codehaus.jackson.map.JsonMappingException: Can not deserialize instance of java.util.ArrayList out of START_OBJECT token at [Source: org.apache.catalina.connector.CoyoteInputStream@6de8c535; line: 1, column: 1] at org.jboss.resteasy.core.MessageBodyParameterInjector.inject(MessageBodyParameterInjector.java:183) at org.jboss.resteasy.core.MethodInjectorImpl.injectArguments(MethodInjectorImpl.java:88) at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:111) at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:280) at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:234) at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:221) at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:356) at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:179) at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:220) at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56) at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:51) at javax.servlet.http.HttpServlet.service(HttpServlet.java:728) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:724)


El problema es que el JSON, por defecto, no se puede deserializar en una Collection porque no es realmente una Matriz JSON, se vería así:

[ { "name": "Test order1", "detail": "ahk ks" }, { "name": "Test order2", "detail": "Fisteku" } ]

Como no está controlando el proceso exacto de deserialización (RestEasy lo hace), una primera opción sería simplemente inyectar el JSON como una String y luego tomar el control del proceso de deserialización:

Collection<COrder> readValues = new ObjectMapper().readValue(jsonAsString, new TypeReference<Collection<COrder>>() { });

Perderías un poco la conveniencia de no tener que hacer eso tú mismo, pero fácilmente resolverías el problema.

Otra opción , si no puede cambiar el JSON, sería construir un contenedor que se ajuste a la estructura de su entrada JSON, y usar eso en lugar de Collection<COrder> .

Espero que esto ayude.


En lugar del documento JSON, puede actualizar el objeto ObjectMapper como se muestra a continuación:

ObjectMapper mapper = new ObjectMapper(); mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);


Tuve este problema en una API REST que se creó usando Spring framework. Agregando una anotación @ResponseBody (para hacer la respuesta JSON) lo resolvió.


Esto funcionará:

El problema puede ocurrir cuando intenta leer una lista con un solo elemento como JsonArray en lugar de JsonNode o viceversa.

Dado que no se puede saber con certeza si la lista devuelta contiene un solo elemento (por lo que el json se ve así {...} ) o múltiples elementos (y el json se ve así [{...}, {... }] ) - tendrás que verificar en tiempo de ejecución el tipo del elemento.

Debe tener un aspecto como este:

(Nota: en este ejemplo de código estoy usando com.fasterxml.jackson)

String jsonStr = response.readEntity(String.class); ObjectMapper mapper = new ObjectMapper(); JsonNode rootNode = mapper.readTree(jsonStr); // Start by checking if this is a list -> the order is important here: if (rootNode instanceof ArrayNode) { // Read the json as a list: myObjClass[] objects = mapper.readValue(rootNode.toString(), myObjClass[].class); ... } else if (rootNode instanceof JsonNode) { // Read the json as a single object: myObjClass object = mapper.readValue(rootNode.toString(), myObjClass.class); ... } else { ... }