JsonMappingException: aucun constructeur approprié trouvé pour type [simple type, class: ne peut pas instancier à partir de l'objet JSON
j'obtiens l'erreur suivante en essayant d'obtenir une requête JSON et de la traiter:
org.codehaus.Jackson.cartographie.JsonMappingException: Pas de constructeur trouvé pour le type [type simple, classe com.myweb.ApplesDO]: ne peut pas instancier à partir de l'objet JSON (besoin d'ajouter/activer des informations de type?)
voici le JSON que j'essaie d'envoyer:
{
"applesDO" : [
{
"apple" : "Green Apple"
},
{
"apple" : "Red Apple"
}
]
}
dans Controller, j'ai le la signature de la méthode suivante:
@RequestMapping("showApples.do")
public String getApples(@RequestBody final AllApplesDO applesRequest){
// Method Code
}
AllApplesDO est un wrapper de 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. S'il vous plaît aidez avec les paramètres de configuration pour Jackson pour convertir JSON en objets Java. Je suis en utilisant le Framework Spring.
EDIT: inclus le bug principal qui cause ce problème dans le au - dessus de la classe d'échantillon-s'il vous plaît regarder réponse acceptée pour la solution.
12 réponses
donc, finalement j'ai réalisé quel était le problème. Ce n'est pas un problème de configuration de Jackson comme j'en doutais.
en fait, le problème était dans ApplesDO Classe:
public class ApplesDO {
private String apple;
public String getApple() {
return apple;
}
public void setApple(String apple) {
this.apple = apple;
}
public ApplesDO(CustomType custom) {
//constructor Code
}
}
il y avait un constructeur personnalisé défini pour la classe en faisant le constructeur par défaut. L'introduction d'un constructeur fictif a fait l'erreur de disparaître:
public class ApplesDO {
private String apple;
public String getApple() {
return apple;
}
public void setApple(String apple) {
this.apple = apple;
}
public ApplesDO(CustomType custom) {
//constructor Code
}
//Introducing the dummy constructor
public ApplesDO() {
}
}
cela se produit pour ces raisons:
-
votre classe intérieure doit être définie comme statique
private static class Condition { //jackson specific }
-
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)
private static class Condition { private Long id; public Condition() { } // Setters and Getters }
-
il se peut que vos Setters ne soient pas définis correctement ou ne soient pas visible (p.ex. setter privé)
je voudrais ajouter une autre solution qui ne nécessite pas de constructeur fictif. Puisque les constructeurs factices sont un peu désordonnés et par la suite confus. 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 constructeur et le champ.
donc la suite. Notez la chaîne à l'intérieur de l'annotation doit correspondre au nom du champ.
import com.fasterxml.jackson.annotation.JsonProperty;
public class ApplesDO {
private String apple;
public String getApple() {
return apple;
}
public void setApple(String apple) {
this.apple = apple;
}
public ApplesDO(CustomType custom){
//constructor Code
}
public ApplesDO(@JsonProperty("apple")String apple) {
}
}
quand je suis tombé sur ce problème, c'était le résultat d'essayer d'utiliser une classe intérieure pour servir comme le faire. La Construction de la classe intérieure (silencieusement) a exigé une instance de la classe enclosante-qui n'était pas disponible pour Jackson.
dans ce cas, faire passer la classe intérieure à elle-même .fichier java résolu le problème.
pouvez-vous tester cette structure? Si je me souviens correct vous pouvez l'utiliser de cette façon:
{
"applesRequest": {
"applesDO": [
{
"apple": "Green Apple"
},
{
"apple": "Red Apple"
}
]
}
}
en Second lieu, s'il vous plaît ajouter constructeur par défaut pour chaque classe, il pourrait également être utiles.
Thumb Rule : Ajouter un constructeur par défaut pour chaque classe que vous avez utilisée comme classe de cartographie. Vous avez manqué ce et question!
Simplement ajouter un constructeur par défaut et cela devrait fonctionner.
vous devez créer le constructeur vide de mannequin dans notre classe de modèle.Ainsi, tout en cartographiant json, il a défini par la méthode setter.
si vous commencez à annoter constructeur, vous devez annoter tous les champs.
avis, Mon personnel.le champ name est associé à" ANOTHER_NAME " dans la chaîne JSON.
String jsonInString="{\"ANOTHER_NAME\":\"John\",\"age\":\"17\"}";
ObjectMapper mapper = new ObjectMapper();
Staff obj = mapper.readValue(jsonInString, Staff.class);
// print to screen
public static class Staff {
public String name;
public Integer age;
public Staff() {
}
//@JsonCreator - don't need this
public Staff(@JsonProperty("ANOTHER_NAME") String n,@JsonProperty("age") Integer a) {
name=n;age=a;
}
}
vous devez réaliser quelles options Jackson A disponibles pour la desérialisation. En Java, les noms d'arguments de méthode ne sont pas présents dans le code compilé. C'est pourquoi Jackson ne peut généralement pas utiliser les 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 vide et les setters. S'il n'y a pas de setters, une magie noire (reflets) est utilisée pour le faire.
si vous voulez utiliser un constructeur avec Jackson, vous devez utiliser les annotations mentionnées par @PiersyP dans sa réponse. Vous pouvez également utiliser un générateur de modèle. Si vous rencontrez quelques exceptions, bonne chance. Le traitement des erreurs dans Jackson craint beaucoup, il est difficile de comprendre ce charabia dans les messages d'erreur.
à Défaut personnalisé jackson Sérialiseurs/Deserializers pourrait également être le problème. Bien que ce ne soit pas votre cas, il vaut la peine de mentionner.
j'ai fait face à la même exception et ce fut le cas.
pour moi, cela fonctionnait, mais la mise à niveau des bibliothèques a fait apparaître ce problème. Le problème était d'avoir une classe comme ceci:
package example.counter;
import javax.validation.constraints.NotNull;
import lombok.Data;
@Data
public class CounterRequest {
@NotNull
private final Integer int1;
@NotNull
private final Integer int2;
}
utilisant lombok:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.0</version>
</dependency>
retour à
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
</dependency>
a réglé le problème. Je ne sais pas pourquoi, mais je voulais le documenter pour l'avenir.
généralement cette erreur vient parce que nous ne faisons pas constructeur par défaut, mais dans mon cas, le problème venait seulement en raison de j'ai fait utilisé classe objet dans la classe parent. Cette a perdu toute ma journée.