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)
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)
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.
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.
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)
il peut être réalisé de 2 manières:
Marquer le POJO pour ignorer les propriétés inconnues
@JsonIgnoreProperties(ignoreUnknown = true)
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)
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é.
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);
Si vous utilisez Jackson 2.0
ObjectMapper mapper = new ObjectMapper();
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
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)
Cela a fonctionné pour moi avec le code suivant:
ObjectMapper mapper =new ObjectMapper();
mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
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".
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
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.
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
}
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 ...
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"}]}
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);
où Wrapper
est défini comme
class Wrapper {
List<Student> wrapper;
}
Ce qui a fonctionné pour moi a été de rendre la propriété publique. Cela a résolu le problème pour moi.
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.
Cela a fonctionné parfaitement pour moi
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
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.
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
définissez public vos champs de classe non privé.
public Class Student {
public String name;
public String id;
//getters & setters for name & id here
}
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);
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.
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
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 get
ter/set
ters. 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;
}
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
}
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.
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.
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.
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
@JsonIgnoreProperties
Vous devriez simplement changer le champ de la liste de "étudiants" à "wrapper" juste le fichier json et le mappeur le recherchera.
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
}