J'obtiens l'erreur suivante lorsque j'essaie d'obtenir une demande JSON et de la traiter:
org.codehaus.jackson.map.JsonMappingException: aucun constructeur approprié trouvé pour le type [type simple, classe com.myweb.ApplesDO]: ne peut pas instancier à partir de l'objet JSON (besoin d'ajouter / activer les informations de type?)
Voici le JSON que j'essaie d'envoyer:
{
"applesDO" : [
{
"apple" : "Green Apple"
},
{
"apple" : "Red Apple"
}
]
}
Dans Controller, j'ai la signature de méthode suivante:
@RequestMapping("showApples.do")
public String getApples(@RequestBody final AllApplesDO applesRequest){
// Method Code
}
AllApplesDO est un wrapper d'ApplesDO:
public class AllApplesDO {
private List<ApplesDO> applesDO;
public List<ApplesDO> getApplesDO() {
return applesDO;
}
public void setApplesDO(List<ApplesDO> applesDO) {
this.applesDO = applesDO;
}
}
ApplesDO:
public class ApplesDO {
private String apple;
public String getApple() {
return apple;
}
public void setApple(String appl) {
this.apple = apple;
}
public ApplesDO(CustomType custom){
//constructor Code
}
}
Je pense que Jackson est incapable de convertir JSON en objets Java pour les sous-classes. Veuillez aider avec les paramètres de configuration pour Jackson pour convertir JSON en objets Java. J'utilise Spring Framework.
EDIT: inclus le bogue majeur à l'origine de ce problème dans l'exemple de classe ci-dessus.
Réponses:
Alors, j'ai finalement réalisé quel était le problème. Ce n'est pas un problème de configuration Jackson comme je le doutais.
En fait, le problème était dans la classe ApplesDO :
Un constructeur personnalisé a été défini pour la classe, ce qui en fait le constructeur par défaut. L'introduction d'un constructeur factice a fait disparaître l'erreur:
la source
Cela se produit pour ces raisons:
votre classe intérieure doit être définie comme statique
Il se peut que vous n'ayez pas de constructeur par défaut dans votre classe ( MISE À JOUR: Cela ne semble pas être le cas)
Il se peut que vos Setters ne soient pas définis correctement ou ne soient pas visibles (par exemple, setter privé)
la source
Je voudrais ajouter une autre solution à cela qui ne nécessite pas de constructeur factice. Étant donné que les constructeurs factices sont un peu désordonnés et confus par la suite. Nous pouvons fournir un constructeur sûr et en annotant les arguments du constructeur, nous permettons à jackson de déterminer la correspondance entre le paramètre du constructeur et le champ.
donc ce qui suit fonctionnera également. Notez que la chaîne à l'intérieur de l'annotation doit correspondre au nom du champ.
la source
@JsonCreator
le constructeur avec@JsonProperty
.Quand j'ai rencontré ce problème, c'était le résultat de l'utilisation d'une classe interne pour servir de DO. La construction de la classe interne (en silence) nécessitait une instance de la classe englobante - qui n'était pas disponible pour Jackson.
Dans ce cas, le déplacement de la classe interne vers son propre fichier .java a résolu le problème.
la source
Généralement, cette erreur vient du fait que nous ne faisons pas de constructeur par défaut, mais dans mon cas, le problème ne venait que parce que j'ai créé la classe d'objets utilisée dans la classe parente. Cela a gâché toute ma journée.
la source
static
.Règle générale : ajoutez un constructeur par défaut pour chaque classe que vous avez utilisée comme classe de mappage. Vous avez raté cela et le problème se pose!
Ajoutez simplement le constructeur par défaut et cela devrait fonctionner.
la source
Pouvez-vous s'il vous plaît tester cette structure. Si je me souviens bien, vous pouvez l'utiliser de cette façon:
Deuxièmement, veuillez ajouter un constructeur par défaut à chaque classe, cela pourrait également aider.
la source
Vous devez créer un constructeur vide factice dans notre classe de modèle. Ainsi, lors du mappage de json, il est défini par la méthode setter.
la source
Si vous commencez à annoter le constructeur, vous devez annoter tous les champs.
Notez que mon champ Staff.name est mappé sur "ANOTHER_NAME" dans la chaîne JSON.
la source
Vous devez comprendre les options dont Jackson dispose pour la désérialisation. En Java, les noms des arguments de méthode ne sont pas présents dans le code compilé. C'est pourquoi Jackson ne peut généralement pas utiliser de constructeurs pour créer un objet bien défini avec tout ce qui est déjà défini.
Donc, s'il y a un constructeur vide et qu'il y a aussi des setters, il utilise le constructeur et les setters vides. S'il n'y a pas de setters, de la magie noire (réflexions) est utilisée pour le faire.
Si vous souhaitez utiliser un constructeur avec Jackson, vous devez utiliser les annotations mentionnées par @PiersyP dans sa réponse. Vous pouvez également utiliser un modèle de générateur. Si vous rencontrez des exceptions, bonne chance. La gestion des erreurs dans Jackson est un gros problème, il est difficile de comprendre ce charabia dans les messages d'erreur.
la source
En ce qui concerne la dernière publication, j'ai eu le même problème lorsque l'utilisation de Lombok 1.18. * A généré le problème.
Ma solution a été d'ajouter @NoArgsConstructor (constructeur sans paramètres), car @Data inclut par défaut @RequiredArgsConstructor (constructeur avec paramètres).
Documentation lombok https://projectlombok.org/features/all
Cela résoudrait le problème:
la source
Le défaut de sérialiseurs / désérialiseurs jackson personnalisés pourrait également être le problème. Bien que ce ne soit pas votre cas, cela vaut la peine d'être mentionné.
J'ai fait face à la même exception et c'était le cas.
la source
Pour moi, cela fonctionnait auparavant, mais la mise à niveau des bibliothèques a provoqué l'apparition de ce problème. Le problème était d'avoir une classe comme celle-ci:
Utilisation de lombok:
Se replier sur
Correction du problème. Je ne sais pas pourquoi, mais je voulais le documenter pour l'avenir.
la source