J'essaye de POSTER un List
des objets personnalisés. Mon JSON dans le corps de la requête est le suivant:
{
"collection": [
{
"name": "Test order1",
"detail": "ahk ks"
},
{
"name": "Test order2",
"detail": "Fisteku"
}
]
}
Code côté serveur qui gère la demande:
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();
}
}
Entité 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() + "]";
}
}
Mais une exception est levée:
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)
Au lieu du document JSON, vous pouvez mettre à jour l'objet ObjectMapper comme ci-dessous:
la source
Cela fonctionnera:
Le problème peut survenir lorsque vous essayez de lire une liste avec un seul élément en tant que JsonArray plutôt que JsonNode ou vice versa.
Puisque vous ne pouvez pas savoir avec certitude si la liste retournée contient un seul élément (donc le json ressemble à ceci {...} ) ou plusieurs éléments (et le json ressemble à ceci [{...}, {... }] ) - vous devrez vérifier à l'exécution le type de l'élément.
Ça devrait ressembler à ça:
(Remarque: dans cet exemple de code, j'utilise com.fasterxml.jackson)
la source
Lié à la réponse d'Eugen, vous pouvez résoudre ce cas particulier en créant un objet POJO wrapper contenant un
Collection<COrder>
comme variable membre. Cela guidera correctement Jackson pour placer lesCollection
données réelles dans la variable membre du POJO et produire le JSON que vous recherchez dans la requête API.Exemple:
Définissez ensuite le type de paramètre de
COrderRestService.postOrder()
comme étant votre nouveauApiRequest
POJO wrapper au lieu deCollection<COrder>
.la source
J'ai rencontré le même problème ces jours-ci et peut-être que des détails supplémentaires pourraient être utiles à quelqu'un d'autre.
Je cherchais des directives de sécurité pour les API REST et j'ai traversé un problème très intriguant avec les tableaux json. Vérifiez le lien pour plus de détails, mais en gros, vous devez les envelopper dans un objet comme nous l'avons déjà vu dans cette question.
Donc, au lieu de:
Il est conseillé de toujours faire:
C'est assez simple lorsque vous effectuez un GET , mais cela pourrait vous poser des problèmes si, à la place, vous essayez de POST / PUT le même json.
Dans mon cas, j'avais plus d'un GET qui était une liste et plus d'un POST / PUT qui recevraient le même json.
Donc, ce que je finis par faire était d'utiliser un objet Wrapper très simple pour une liste :
La sérialisation de mes listes a été faite avec un @ControllerAdvice :
Ainsi, toutes les listes et cartes étaient enveloppées sur un objet de données comme ci-dessous:
La désérialisation était toujours par défaut, en utilisant simplement de Wrapper Object:
C'était ça! J'espère que ça aide quelqu'un.
Remarque: testé avec SpringBoot 1.5.5.RELEASE .
la source
J'ai eu ce problème sur une API REST créée à l'aide du framework Spring. L'ajout d'une annotation @ResponseBody (pour rendre la réponse JSON) l'a résolu.
la source
Normalement, nous sommes confrontés à ce problème lorsqu'il y a un problème de mappage du nœud JSON avec celui de l'objet Java. J'ai rencontré le même problème parce que dans le swagger, le nœud était défini comme un tableau Type et que l'objet JSON n'avait qu'un seul élément, le système avait donc du mal à mapper une liste d'éléments à un tableau.
Dans Swagger, l'élément était défini comme
Alors que ça devrait être
Et
TestNew
devrait être de type arrayla source
la source
Même problème:
La cause en était la suivante:
Dans mon test, j'ai volontairement défini la demande comme nulle (pas de contenu POST). Comme mentionné précédemment, la cause de l'OP était la même car la requête ne contenait pas de JSON valide, elle ne pouvait donc pas être automatiquement identifiée comme une requête application / json, ce qui était la limitation du serveur (
consumes = "application/json"
). Une demande JSON valide serait. Ce qui a résolu le problème, c'était de remplir explicitement une entité avec un corps nul et des en-têtes json.la source
Dans mon cas, l'erreur était affichée car lorsque je lisais mon fichier JSON à l'aide de la bibliothèque Jackson, mon fichier JSON ne contenait qu'un seul objet. Par conséquent, il a commencé par "{" et s'est terminé par "}". Mais en le lisant et en le stockant dans une variable, je le stockais dans un objet Array (comme dans mon cas, il pourrait y avoir plus d'un objet).
Par conséquent, j'ai ajouté "[" au début et "]" à la fin de mon fichier JSON pour le convertir en un tableau d'objets et cela a parfaitement fonctionné sans aucune erreur.
la source
Comme mentionné ci-dessus, ce qui suit résoudrait le problème:
mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
Cependant, dans mon cas, le fournisseur a fait cette sérialisation [0..1] ou [0 .. *] plutôt comme un bogue et je n'ai pas pu appliquer la correction. Par contre cela ne voulait pas impacter mon mappeur strict pour tous les autres cas qui doivent être validés strictement.
J'ai donc fait un Jackson NASTY HACK (qui ne devrait pas être copié en général ;-)), surtout parce que mon SingleOrListElement n'avait que quelques propriétés à corriger:
la source
@JsonFormat (avec = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY) Liste privée des commandes <COrder>;
la source