web-dev-qa-db-fra.com

Jackson avec JSON: champ non reconnu, non marqué comme ignorable

Je dois convertir une certaine chaîne JSON en un objet Java. J'utilise Jackson pour la gestion JSON. Je n'ai aucun contrôle sur le JSON d'entrée (je lis depuis un service Web). Ceci est mon entrée JSON:

{"wrapper":[{"id":"13","name":"Fred"}]}

Voici un cas d'utilisation simplifié:

private void tryReading() {
    String jsonStr = "{\"wrapper\"\:[{\"id\":\"13\",\"name\":\"Fred\"}]}";
    ObjectMapper mapper = new ObjectMapper();  
    Wrapper wrapper = null;
    try {
        wrapper = mapper.readValue(jsonStr , Wrapper.class);
    } catch (Exception e) {
        e.printStackTrace();
    }
    System.out.println("wrapper = " + wrapper);
}

Ma classe d'entité est:

public Class Student { 
    private String name;
    private String id;
    //getters & setters for name & id here
}

Ma classe Wrapper est fondamentalement un objet conteneur pour obtenir ma liste d'étudiants:

public Class Wrapper {
    private List<Student> students;
    //getters & setters here
}

Je continue à avoir cette erreur et "wrapper" renvoie null. Je ne suis pas sûr de ce qui manque. Quelqu'un peut aider s'il vous plaît?

org.codehaus.jackson.map.exc.UnrecognizedPropertyException: 
    Unrecognized field "wrapper" (Class Wrapper), not marked as ignorable
 at [Source: Java.io.StringReader@1198891; line: 1, column: 13] 
    (through reference chain: Wrapper["wrapper"])
 at org.codehaus.jackson.map.exc.UnrecognizedPropertyException
    .from(UnrecognizedPropertyException.Java:53)
576
jshree

Vous pouvez utiliser l'annotation de classe de Jackson:

import com.fasterxml.jackson.annotation.JsonIgnoreProperties

@JsonIgnoreProperties
class { ... }

Il ignorera toutes les propriétés que vous n'avez pas définies dans votre POJO. Très utile lorsque vous recherchez quelques propriétés dans le JSON et que vous ne voulez pas écrire le mappage complet. Plus d'infos sur site de Jackson . Si vous souhaitez ignorer une propriété non déclarée, vous devez écrire:

@JsonIgnoreProperties(ignoreUnknown = true)
883
Ariel Kogan

Vous pouvez utiliser

ObjectMapper objectMapper = getObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

Il ignorera toutes les propriétés non déclarées.

412

La première réponse est presque correcte, mais il est nécessaire de changer de méthode getter, champ NOT - champ est privé (et non auto-détecté); de plus, les getters ont priorité sur les champs si les deux sont visibles (il existe des moyens de rendre les champs privés visibles également, mais si vous voulez avoir le getter, cela ne sert à rien).

Donc, le getter devrait être nommé getWrapper() ou annoté avec:

@JsonProperty("wrapper")

Si vous préférez le nom de la méthode getter tel quel.

120
StaxMan

en utilisant Jackson 2.6.0, cela a fonctionné pour moi:

private static final ObjectMapper objectMapper = 
    new ObjectMapper()
        .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

et avec réglage:

@JsonIgnoreProperties(ignoreUnknown = true)
78
Scott

il peut être réalisé de 2 manières:

  1. Marquer le POJO pour ignorer les propriétés inconnues

    @JsonIgnoreProperties(ignoreUnknown = true)
    
  2. Configurez ObjectMapper qui sérialise/désérialise le POJO/json comme ci-dessous:

    ObjectMapper mapper =new ObjectMapper();            
    // for Jackson version 1.X        
    mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    // for Jackson version 2.X
    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) 
    
49
Anamika

Cela a parfaitement fonctionné pour moi

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(
    DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);

L'annotation @JsonIgnoreProperties(ignoreUnknown = true) ne l'a pas été.

39
Felix Kimutua

Cela fonctionne mieux que tous s'il vous plaît se référer à cette propriété.

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;

    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    projectVO = objectMapper.readValue(yourjsonstring, Test.class);
35
Karan

Si vous utilisez Jackson 2.0

ObjectMapper mapper = new ObjectMapper();
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
26
Aalkhodiry

Selon le doc vous pouvez ignorer les champs sélectionnés ou tous les champs inconnus:

 // to prevent specified fields from being serialized or deserialized
 // (i.e. not include in JSON output; or being set even if they were included)
 @JsonIgnoreProperties({ "internalId", "secretKey" })

 // To ignore any unknown properties in JSON input without exception:
 @JsonIgnoreProperties(ignoreUnknown=true)
18
tomrozb

Cela a fonctionné pour moi avec le code suivant:

ObjectMapper mapper =new ObjectMapper();    
mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
14
vaibhav nirkhe

Jackson se plaint car il ne trouve pas de champ dans votre classe Wrapper appelé "wrapper". C'est parce que votre objet JSON a une propriété appelée "wrapper".

Je pense que la solution consiste à renommer le champ de votre classe Wrapper en "wrapper" au lieu de "étudiants".

12
Jim Ferrans

J'ai essayé la méthode ci-dessous et cela fonctionne pour une telle lecture de format JSON avec Jackson. Utilisez la solution déjà suggérée de: annoter le getter avec @JsonProperty("wrapper")

Votre classe d'emballage

public Class Wrapper{ 
  private List<Student> students;
  //getters & setters here 
} 

Ma suggestion de classe d'emballage

public Class Wrapper{ 

  private StudentHelper students; 

  //getters & setters here 
  // Annotate getter
  @JsonProperty("wrapper")
  StudentHelper getStudents() {
    return students;
  }  
} 


public class StudentHelper {

  @JsonProperty("Student")
  public List<Student> students; 

  //CTOR, getters and setters
  //NOTE: If students is private annotate getter with the annotation @JsonProperty("Student")
}

Cela vous donnerait cependant la sortie du format:

{"wrapper":{"student":[{"id":13,"name":Fred}]}}

De plus, pour plus d'informations, consultez https://github.com/FasterXML/jackson-annotations

J'espère que cela t'aides

12
mytwocentsads

Cette solution est générique lors de la lecture de flux JSON et ne doit contenir que certains champs, tandis que les champs mal mappés dans vos classes de domaine peuvent être ignorés:

import org.codehaus.jackson.annotate.JsonIgnoreProperties;
@JsonIgnoreProperties(ignoreUnknown = true)

Une solution détaillée consisterait à utiliser un outil tel que jsonschema2pojo pour générer automatiquement les classes de domaine requises, telles que Student, à partir du schéma de la réponse json. Vous pouvez faire le dernier en utilisant n'importe quel convertisseur JSON en schéma en ligne.

10

Annotez les étudiants sur le terrain comme indiqué ci-dessous car les noms des propriétés json et Java sont incompatibles.

public Class Wrapper {
    @JsonProperty("wrapper")
    private List<Student> students;
    //getters & setters here
}
9
ajith r

Comme personne d'autre ne l'a mentionné, je pensais ...

Le problème est que votre propriété dans votre JSON est appelée "wrapper" et votre propriété dans Wrapper.class est appelée "étudiants".

Alors soit ...

  1. Corrigez le nom de la propriété dans la classe ou JSON.
  2. Annotez votre variable de propriété selon le commentaire de StaxMan.
  3. Annoter le passeur (si vous en avez un)
8
TedTrippin

Soit changer

public Class Wrapper {
    private List<Student> students;
    //getters & setters here
}

à

public Class Wrapper {
    private List<Student> wrapper;
    //getters & setters here
}

---- ou ----

Changez votre chaîne JSON en

{"students":[{"id":"13","name":"Fred"}]}
5
sagar

Votre entrée

{"wrapper":[{"id":"13","name":"Fred"}]}

indique qu'il s'agit d'un objet, avec un champ nommé "wrapper", qui est une collection d'étudiants. Donc, ma recommandation serait,

Wrapper = mapper.readValue(jsonStr , Wrapper.class);

Wrapper est défini comme

class Wrapper {
    List<Student> wrapper;
}
5
Ran0990BK

Ce qui a fonctionné pour moi a été de rendre la propriété publique. Cela a résolu le problème pour moi.

4
Rohitesh

La nouvelle Firebase Android a introduit d’énormes changements; sous la copie du document:

[ https://firebase.google.com/support/guides/firebase-Android]:

Mettez à jour vos objets de modèle Java

Comme avec le SDK 2.x, la base de données Firebase convertit automatiquement les objets Java que vous transmettez à DatabaseReference.setValue() en JSON et peut lire JSON dans les objets Java à l'aide de DataSnapshot.getValue().

Dans le nouveau SDK, lors de la lecture de JSON dans un objet Java avec DataSnapshot.getValue(), les propriétés inconnues dans JSON sont désormais ignorées par défaut, de sorte que vous n'avez plus besoin de @JsonIgnoreExtraProperties(ignoreUnknown=true).

Pour exclure les champs/getters lors de l'écriture d'un objet Java dans JSON, l'annotation est maintenant appelée @Exclude au lieu de @JsonIgnore.

BEFORE

@JsonIgnoreExtraProperties(ignoreUnknown=true)
public class ChatMessage {
   public String name;
   public String message;
   @JsonIgnore
   public String ignoreThisField;
}

dataSnapshot.getValue(ChatMessage.class)

AFTER

public class ChatMessage {
   public String name;
   public String message;
   @Exclude
   public String ignoreThisField;
}

dataSnapshot.getValue(ChatMessage.class)

S'il existe une propriété supplémentaire dans votre JSON qui n'est pas dans votre classe Java, cet avertissement apparaît dans les fichiers journaux:

W/ClassMapper: No setter/field for ignoreThisProperty found on class com.firebase.migrationguide.ChatMessage

Vous pouvez vous débarrasser de cet avertissement en mettant une annotation @IgnoreExtraProperties sur votre classe. Si vous voulez que la base de données Firebase se comporte comme dans le SDK 2.x et lève une exception s'il existe des propriétés inconnues, vous pouvez ajouter une annotation @ThrowOnExtraProperties sur votre classe.

4
ThierryC

Cela a fonctionné parfaitement pour moi

objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
4
Niamath

J'ai résolu ce problème en changeant simplement les signatures de mes méthodes setter et getter de ma classe POJO. Tout ce que je devais faire était de changer la méthode getObject pour correspondre à ce que le mappeur cherchait. Dans mon cas, j’avais un getImageUrl à l’origine, mais les données JSON avaient image_url, ce qui lançait le mappeur. J'ai changé mon passeur et mes accesseurs en getImage_url et setImage_url.

J'espère que cela t'aides.

4
superuserdo

Pour ma part, la seule ligne

@JsonIgnoreProperties(ignoreUnknown = true)

n'a pas fonctionné aussi.

Il suffit d'ajouter

@JsonInclude(Include.NON_EMPTY)

Jackson 2.4.0

4
jodu

définissez public vos champs de classe non privé.

public Class Student { 
    public String name;
    public String id;
    //getters & setters for name & id here
}
3
neverwinter

Le POJO doit être défini comme

Classe de réponse

public class Response {
    private List<Wrapper> wrappers;
    // getter and setter
}

Classe d'emballage

public class Wrapper {
    private String id;
    private String name;
    // getters and setters
}

et mappeur pour lire la valeur

Response response = mapper.readValue(jsonStr , Response.class);
3
Dino Tw

Une autre possibilité est cette propriété dans le fichier application.properties spring.jackson.deserialization.fail-on-unknown-properties=false, qui ne nécessite aucun autre changement de code dans votre application. Et lorsque vous pensez que le contrat est stable, vous pouvez supprimer cette propriété ou la marquer comme étant vraie.

3
krmanish007

Ce n'est peut-être pas le même problème que l'OP, mais si quelqu'un venait ici avec la même erreur que moi, cela les aiderait à résoudre leur problème. J'ai eu la même erreur que l'OP lorsque j'ai utilisé un ObjectMapper provenant d'une dépendance différente de l'annotation JsonProperty.

Cela marche:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.annotation.JsonProperty;

Ne marche pas:

import org.codehaus.jackson.map.ObjectMapper; //org.codehaus.jackson:jackson-mapper-asl:1.8.8
import com.fasterxml.jackson.annotation.JsonProperty; //com.fasterxml.jackson.core:jackson-databind:2.2.3
2
cwa

Google m'a amené ici et j'ai été surpris de voir les réponses ... tout suggéré en contournant l'erreur ( qui toujours réplique 4 fois plus tard dans le développement ) plutôt que de le résoudre jusqu'à ce que ce monsieur restauré par la foi en SO!

objectMapper.readValue(responseBody, TargetClass.class)

est utilisé pour convertir une chaîne json en un objet de classe, ce qui manque est que la TargetClass devrait avoir public getter/setters. Idem manque aussi dans l'extrait de question d'OP! :)

via lombok votre classe comme ci-dessous devrait fonctionner !!

@Data
@Builder
public class TargetClass {
    private String a;
}
2
NoobEditor

Cela peut être une réponse très tardive, mais changer simplement le POJO en ceci devrait résoudre la chaîne JSON fournie dans le problème (puisque la chaîne d'entrée n'est pas sous votre contrôle comme vous l'avez dit):

public class Wrapper {
    private List<Student> wrapper;
    //getters & setters here
}
2
Sayantan

Dans mon cas, c'était simple: l'objet JSON du service REST a été mis à jour (une propriété a été ajoutée), mais pas l'objet JSON du client REST. Dès que j'ai mis à jour l'objet client JSON, l'exception "Champ non reconnu ..." a disparu.

1
blue-bird

Remplacez la classe Wrapper par

public Class Wrapper {

          @JsonProperty("wrapper")  // add this line
          private List<Student> students;
}

Cela permet de reconnaître le champ students comme étant la clé wrapper de l'objet json.

Personnellement, je préfère aussi utiliser Annotations de Lombok pour les Getters et les Setters comme

@Getter
@Setter
public Class Wrapper {

          @JsonProperty("wrapper")  // add this line
          private List<Student> students;
}

Puisque je n'ai pas testé le code ci-dessus avec Lombok et @JsonProperty ensemble, je vous suggère d'ajouter le code suivant à la classe Wrapper afin de remplacer le getter et le setter par défaut de Lombok.

public List<Student> getWrapper(){
     return students;
}

public void setWrapper(List<Student> students){
     this.students = students;
}

Vérifiez également this pour désérialiser les listes à l'aide de Jackson.

0
devilsbane

Dans mon cas, l'erreur est due à la raison suivante

  • Au début, cela fonctionnait bien, puis j’ai renommé une variable, apporté les modifications de code et c’est ce qui m’a causé cette erreur.

  • Ensuite, j’ai appliqué la propriété ignorante jackson également, mais cela n’a pas fonctionné.

  • Enfin, après avoir redéfini mes méthodes d’obtention et d’ajustage en fonction du nom de ma variable, cette erreur a été résolue.

Donc, assurez-vous de redéfinir les getters et les setters également.

0
Vikram Saini

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties

0
Gank

Vous devriez simplement changer le champ de la liste de "étudiants" à "wrapper" juste le fichier json et le mappeur le recherchera.

0
Troy

Votre chaîne json n'est pas alignée avec la classe mappée. Changer la chaîne de saisie

String jsonStr = "{\"students\"\:[{\"id\":\"13\",\"name\":\"Fred\"}]}";

Ou changez de classe

public class Wrapper {
    private List<Student> wrapper;
    //getters & setters here
}
0
xLime