Deserializar JSON en un objeto existente (Java)

Me gustaría saber cómo se puede obtener la biblioteca Jackson JSON para deserializar JSON en un objeto existente. He tratado de encontrar cómo hacerlo; pero parece que solo es capaz de tomar una clase y crear una instancia de sí mismo.

O si no es posible, me gustaría saber si cualquier biblioteca de deserialización Java JSON puede hacerlo.

Esta parece ser una pregunta correspondiente para C #: Superponer datos de cadena JSON a instancia de objeto existente . Parece que JSON.NET tiene un PopulateObject (cadena, objeto).

Puedes hacer esto usando Jackson:

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

Véase también la fusión de dos documentos JSON con Jackson

Si puede usar otra biblioteca en lugar de Jackson, puede probar Genson http://owlike.github.io/genson/ . Además de algunas otras funciones agradables (como deserializar utilizando un constructor no vacío sin anotación, deserializar a tipos polimórficos, etc.), admite la deserialización de JavaBean en una instancia existente. Aquí hay un ejemplo:

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

Si tiene alguna pregunta, no dude en utilizar su lista de correo http://groups.google.com/group/genson .

Si está utilizando Spring Framework, puede usar la biblioteca de BeanUtils para esta tarea. Primero deserialice su cadena json normalmente y luego use BeanUtils para establecer este objeto dentro de un objeto principal. También espera que el nombre de la variable del objeto se establezca dentro del objeto principal. Aquí está el fragmento de código:

 childObject = gson.fromJson("your json string",class.forName(argType)) BeanUtils.setProperty(mainObject, "childObjectName", childObject); 

Una solución es analizar un nuevo gráfico / árbol de objetos y luego unificar-copiar en el gráfico / árbol de objetos existente. Pero eso es por supuesto menos eficiente y más trabajo, especialmente si los tipos concretos difieren debido a la menor disponibilidad de información tipo. (Entonces realmente no es una respuesta. Espero que haya una mejor respuesta, solo quiero evitar que otros respondan de esta manera).

flexJson también puede ayudarte a hacer lo mismo.

Aquí hay un ejemplo copiado de FlexJson Doc

La función deserializeInto toma su cadena y referencia al objeto existente.

  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().deserializeInto(json, charlieClone); 

Tenga en cuenta que la referencia devuelta en p es igual que charlieClone solo con valores actualizados.

Utilicé DataBinder de Jackson + Spring para lograr algo como esto. Este código maneja matrices pero no objetos nesteds.

 private void bindJSONToObject(Object obj, String json) throws IOException, JsonProcessingException { MutablePropertyValues mpv = new MutablePropertyValues(); JsonNode rootNode = new ObjectMapper().readTree(json); for (Iterator> iter = rootNode.getFields(); iter.hasNext(); ) { Entry entry = iter.next(); String name = entry.getKey(); JsonNode node = entry.getValue(); if (node.isArray()) { List values = new ArrayList(); 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); } 

siempre podría cargarse en un objeto ficticio y usar la reflexión para transferir los datos. si tu corazón está configurado con solo usar gson

ejemplo. suponiendo que este código está en el objeto en el que desea copiar datos

  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 tempFields = new ArrayList(); ArrayList ourFields = new ArrayList(); 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 getAllFields(List fields, Class< ?> type) { for (Field field : type.getDeclaredFields()) { fields.add(field); } if (type.getSuperclass() != null) { fields = getAllFields(fields, type.getSuperclass()); } return fields; }