Deserialiser JSON dans un objet existant (Java)

j'aimerais savoir comment on peut amener la bibliothèque Jackson JSON à desérialiser JSON en un objet existant? J'ai essayé de trouver comment le faire, mais il semble être seulement en mesure de prendre un cours et instanciate lui-même.

ou si ce n'est pas possible, j'aimerais savoir si des bibliothèques de desérialisation Java JSON peuvent le faire.

cela semble être une question correspondante pour C#: données de superposition de la chaîne JSON à l'instance d'objet existante . Il semble JSON.NET a un objet PopulateObject (string,object).

26
demandé sur msrd0 2012-09-20 22:25:19

7 réponses

vous pouvez le faire en utilisant Jackson:

mapper.readerForUpdating(object).readValue(json);

Voir aussi la Fusion des Deux Documents JSON à l'Aide de Jackson

48
répondu Johan Boberg 2017-05-23 10:31:13

si vous pouvez utiliser une autre bibliothèque au lieu de Jackson, vous pouvez essayer Genson http://owlike.github.io/genson / . En plus de quelques autres fonctionnalités intéressantes (telles que deserialize utilisant un constructeur non vide sans aucune annotation, deserialize à des types polymorphiques, etc) il supporte la desérialisation de JavaBean dans une instance existante. Voici un exemple:

BeanDescriptorProvider provider = new Genson().getBeanDescriptorFactory();
BeanDescriptor<MyClass> descriptor = provider.provide(MyClass.class, genson);
ObjectReader reader = new JsonReader(jsonString);
MyClass existingObject = descriptor.deserialize(existingObject, reader, new Context(genson));

si vous avez des questions n'hésitez pas à utiliser sa liste de diffusion http://groups.google.com/group/genson .

1
répondu eugen 2014-06-27 11:18:16

si vous utilisez spring framework, vous pouvez utiliser la bibliothèque BeanUtils pour cette tâche. Tout d'abord, désérialisez votre chaîne json normalement, puis utilisez BeanUtils pour placer cet objet à l'intérieur d'un objet parent. Il attend également de la variable nom de l'objet à définir à l'intérieur de l'objet parent. Voici l'extrait de code:

childObject = gson.fromJson("your json string",class.forName(argType))
BeanUtils.setProperty(mainObject, "childObjectName", childObject);
1
répondu yokesh sharma 2015-08-06 07:25:55

Une solution consiste à analyser un nouvel objet graphique/arbre, et ensuite unifier-copie de l'objet graphique/arbre. Mais c'est évidemment moins efficace, et plus de travail, surtout si les types concrets diffèrent en raison de la moins grande disponibilité de l'information sur les types. (Donc pas vraiment une réponse. J'espère qu'il y a une meilleure réponse, je veux juste éviter que d'autres répondent de cette façon.)

0
répondu Jonas N 2012-09-20 18:25:19

flexJson peut également vous aider à faire de même.

voici un exemple copié de FlexJson Doc

la fonction deserializeInto prend votre chaîne et référence à l'objet existant.

 Person charlie = new Person("Charlie", "Hubbard", cal.getTime(), home, work );
 Person charlieClone = new Person( "Chauncy", "Beauregard", null, null, null );
 Phone fakePhone = new Phone( PhoneNumberType.MOBILE, "303 555 1234");
 charlieClone.getPhones().add( fakePhone ); 
 String json = new JSONSerializer().include("hobbies").exclude("firstname", "lastname").serialize( charlie ); 
 Person p = new JSONDeserializer<Person>().deserializeInto(json, charlieClone);

notez que la référence retournée en p est la même que charlieClone juste avec les valeurs mises à jour.

0
répondu faizan 2012-10-12 12:34:35

j'ai utilisé la base de données de Jackson + Spring pour accomplir quelque chose comme ça. Ce code gère les tableaux, mais pas les objets imbriqués.

private void bindJSONToObject(Object obj, String json) throws IOException, JsonProcessingException {
    MutablePropertyValues mpv = new MutablePropertyValues();
    JsonNode rootNode = new ObjectMapper().readTree(json);
    for (Iterator<Entry<String, JsonNode>> iter = rootNode.getFields(); iter.hasNext(); ) {
        Entry<String, JsonNode> entry = iter.next();
        String name = entry.getKey();
        JsonNode node = entry.getValue();
        if (node.isArray()) {
            List<String> values = new ArrayList<String>();
            for (JsonNode elem : node) {
                values.add(elem.getTextValue());
            }
            mpv.addPropertyValue(name, values);
            if (logger.isDebugEnabled()) {
                logger.debug(name + "=" + ArrayUtils.toString(values));
            }
        }
        else {
            mpv.addPropertyValue(name, node.getTextValue());
            if (logger.isDebugEnabled()) {
                logger.debug(name + "=" + node.getTextValue());
            }
        } 
    }
    DataBinder dataBinder = new DataBinder(obj);
    dataBinder.bind(mpv);
}
0
répondu splashout 2013-05-09 18:23:49

peut toujours charger dans un objet factice et utiliser la réflexion pour transférer les données. si votre cœur est mis sur juste en utilisant gson

exemple. en supposant que ce code est dans l'objet que vous voulez copier les données dans

    public void loadObject(){
Gson gson = new Gson();
//make temp object
YourObject tempStorage = (YourObject) gson.fromJson(new FileReader(theJsonFile), YourObject.class);
//get the fields for that class
ArrayList<Field> tempFields = new ArrayList<Field>();
ArrayList<Field> ourFields = new ArrayList<Field>();
getAllFields(tempFields, tempStorage.getClass());
getAllFields(thisObjectsFields, this.getClass());
for(Field f1 : tempFields){
    for(Field f2 : thisObjectsFields){
        //find matching fields
        if(f1.getName().equals(f2.getName()) && f1.getType().equals(f2.getType())){
            //transient and statics dont get serialized and deserialized.
            if(!Modifier.isTransient(f1.getModifiers())&&!Modifier.isStatic(f1.getModifiers())){
                //make sure its a loadable thing
                f2.set(this, f1.get(tempStorage));
            }
        }
    }
}

}

public static List<Field> getAllFields(List<Field> fields, Class<?> type) {
    for (Field field : type.getDeclaredFields()) {
        fields.add(field);
    }
    if (type.getSuperclass() != null) {
        fields = getAllFields(fields, type.getSuperclass());
    }
    return fields;
}

0
répondu Jordan Haynes 2014-09-16 20:44:15