Je dois désérialiser un objet JSON plat en un objet Java avec certaines propriétés définies sur un objet enfant.
Class Student { String name; Address address; } Class Address { String line1; String line2; }
{ "name": "abcd", "addressLine1": "123", "addressLine2": "1111" }
Comment désérialiser mon JSON à l'aide de Jackson en un objet Student
?
Je ne peux pas mapper addressLine1 à Student.Address.line1
et addressLine2 à Student.Address.line2
4 Réponses :
Avant tout, assurez-vous d'avoir jackson-databind a > dans vos dépendances ou bibliothèques. Voici ce que vous pouvez faire: La désérialisation directe dans un objet de classe signifierait que la classe et la chaîne Json ont exactement les mêmes propriétés. Ce qui n'est pas le cas ici. D'où le bouclage avec for et l'utilisation de mutateurs. Lisez ceci pour plus de détails String jsonInput = // You JSON String here;
TypeReference<HashMap<String, String>> typeRef
= new TypeReference<HashMap<String, String>>() {};
Map<String, String> map = mapper.readValue(jsonInput, typeRef);
Student student = new Student();
Address address = new Address();
for (Map.Entry<String, String> entry : map.entrySet())
{
if(((String)entry.getKey()).equals("addressLine1")){
student.setName(map.get("name"));
student.setAddress(map.get("addressLine1"));
}
if(((String)entry.getKey()).equals("addressLine2")){
address.setLine1(map.get("addressLine1"));
address.setLine2(map.get("addressLine2"));
}
//System.out.println(entry.getKey() + "/" + entry.getValue());
}
Vous pouvez utiliser ObjectMapper comme ceci:
Class Student{ String name; String addressLine1; String addressLine2; }
Mais vous devez également modifier la classe Student comme suit avec tous les getters et setters implémentés:
ObjectMapper objectMapper = new ObjectMapper(); Student student = objectMapper.readValue(json, Student.class);
EDIT: Tant que mes solutions fonctionnent, la réponse de Selindek est la meilleure
Votre Json n'est pas valide selon https://jsonlint.com/ pour 2 raisons:
Je vais assumer ce JSON, avec des noms de champs sans guillemets:
mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
Je peux penser à 2 approches:
1 - Traitement simple des cartes
{ "name": "abcd", "addressLine1": "123", "addressLine2": "1111" }
2 - Utilisation d'un objet Proxy (je préférerais celui-ci)
Une autre approche serait d'avoir une classe proxy dans laquelle vous pouvez désérialiser votre JSON, et construire votre étudiant à partir de celui-ci:
// Create your mapper, and configure it to allow unquoted field names ObjectMapper mapper = new ObjectMapper(); mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); // Parse the JSON to a RawStudent object RawStudent rawStudent = null; try { rawStudent = mapper.readValue(jsonUnquoted, RawStudent.class); } catch (Exception e) { System.out.println("Something went wrong:" + e.getMessage()); } // Read the data from the map and build your objects Student student = null; if (rawStudent != null) { student = rawStudent.toStudent(); System.out.println(student.getName()); System.out.println(student.getAddress().getLine1()); System.out.println(student.getAddress().getLine2()); }
Et l'utiliser de cette façon: p >
class RawStudent { private String name, addressLine1, addressLine2; public Student toStudent() { Address address = new Address(); address.setLine1(addressLine1); address.setLine2(addressLine2); Student student = new Student(); student.setName(name); student.setAddress(address); return student; } // GETTERS / SETTERS }
REMARQUE
Si vous avez mal saisi et avez effectivement cité des champs, par exemple:
// Create your mapper, and configure it to allow unquoted field names ObjectMapper mapper = new ObjectMapper(); mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); // Parse the JSON to a Map TypeReference<HashMap<String, String>> typeRef = new TypeReference<HashMap<String, String>>() {}; Map<String, String> jsonAsMap = null; try { jsonAsMap = mapper.readValue(yourJsonString, typeRef); } catch (Exception e) { System.out.println("Something went wrong:" + e.getMessage()); } // Read the data from the map and build your objects Student student = null; if(jsonAsMap != null) { Address address = new Address(); address.setLine1(jsonAsMap.get("addressLine1")); address.setLine2(jsonAsMap.get("addressLine2")); student = new Student(); student.setName(jsonAsMap.get("name")); student.setAddress(address); System.out.println(student.getName()); System.out.println(student.getAddress().getLine1()); System.out.println(student.getAddress().getLine2()); }
Alors vous n'avez pas besoin de cette ligne
{ name: "abcd", addressLine1: "123", addressLine2: "1111" }
Vous pouvez définir vos classes de données de cette manière:
mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
Ensuite, vous pouvez utiliser l ' Objectmapper
de la manière habituelle - sans magie supplémentaire ni solution de contournement: p>
Student student = mapper.readValue(json, Student.class);
Si votre chaîne json entrante est effectivement au format que vous avez fourni (sans guillemets), ajoutez également:
public static class Student { String name; @JsonUnwrapped Address address; } public static class Address { @JsonProperty("addressLine1") String line1; @JsonProperty("addressLine2") String line2; }
Agréable! Je ne connaissais pas cette annotation @JsonUnwrapped
. Je pense que vous devez annoter l'attribut name
avec @JsonProperty
.
Vous pouvez également annoter la propriété name, mais ce n'est pas nécessaire, car le nom de la propriété dans la classe et le nom de la propriété dans la chaîne json sont identiques.
J'ai simplement soulevé le problème parce que j'ai essayé de l'exécuter et que cela ne fonctionnait pas pour moi sans l'annotation.
C'est intéressant. Je l'ai essayé avant de publier la réponse et cela a fonctionné pour moi avec plus rapidexml 2.9.8. Peut-être que vous utilisez un autre package ou version avec des paramètres par défaut différents.
Je suppose que cela n'a pas vraiment d'importance, ce n'est pas de toute façon la question qui se pose :)
êtes-vous sûr du json? name, addressLine1 et addressLine2 ne sont-ils pas entre guillemets? aussi la virgule après "1111" le rend invalide.