2012-09-20 38 views
26

Ich würde gerne wissen, wie man die Jackson JSON-Bibliothek dazu bringen kann, JSON in ein bestehendes Objekt zu deserialisieren? Ich habe versucht, das zu finden; aber es scheint nur in der Lage zu sein, eine Klasse zu nehmen und sie selbst zu instantiieren.Deserialisieren von JSON in vorhandenes Objekt (Java)

Oder, wenn nicht möglich, würde ich gerne wissen, ob Java Deserialisierung Bibliotheken JSON es tun können.

Dies scheint eine entsprechende Frage für C# zu sein: Overlay data from JSON string to existing object instance. Es scheint, dass JSON.NET ein PopulateObject (String, Objekt) hat.

+0

Haben Sie sich Gson angesehen? http://code.google.com/p/google-gson/ – yodamad

+0

Nur oberflächlich. Kann es das oben tun? –

+0

Scheint, es gibt ein Gson Problem "Problem 431: Bestehendes Objekt füllen" unter http://code.google.com/p/google-gson/issues/detail?id=431 –

Antwort

39

Sie können diesen mit Jackson tun:

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

Siehe auch Merging Two JSON Documents Using Jackson

+0

Danke, @boberj - Seltsam, dass es niemandem zuvor gelungen ist; Das Feature muss in Jackson gewesen sein, als ich gefragt habe, da Ihr Link zu einer älteren Antwort ist, die dies beschreibt. –

+1

Aber leider wird 'readValue' in diesem Fall keine Ausnahmen auslösen, wenn' json' nicht parsen kann. Ist es möglich, das Verhalten wieder normal zu machen? – Hubbitus

0

Eine Lösung besteht darin, ein neues Objektdiagramm/einen neuen Baum zu parsen und dann in das vorhandene Objektdiagramm/den vorhandenen Baum zu kopieren. Aber das ist natürlich weniger effizient und mehr Arbeit, insbesondere wenn sich konkrete Typen aufgrund der geringeren Verfügbarkeit von Typinformationen unterscheiden. (Also nicht wirklich eine Antwort. Ich hoffe, es gibt eine bessere Antwort, nur vermeiden wollen, dass andere auf diese Weise antworten.)

1

Wenn Sie eine andere Bibliothek anstelle von Jackson verwenden können Sie versuchen, Genson http://owlike.github.io/genson/. Zusätzlich zu einigen anderen netten Features (wie Deserialisierung mit einem nicht leeren Konstruktor ohne jegliche Annotation, Deserialisierung zu polymorphen Typen usw.) unterstützt es die Deserialisierung von JavaBean in eine existierende Instanz. Hier ein Beispiel:

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)); 

Wenn Sie Fragen haben, zögern Sie nicht, ihre Mailingliste verwenden http://groups.google.com/group/genson.

+0

Danke, ich werde auf jeden Fall einen Blick darauf werfen! Hier ist ihr erstes Ziel, und es sieht vielversprechend aus: "Sei so erweiterbar wie möglich, indem es Benutzern erlaubt, neue Funktionen auf eine saubere und einfache Weise hinzuzufügen. Genson wendet die Philosophie an: "Wir können nicht an jeden Anwendungsfall denken, also geben Sie den Benutzern die Fähigkeit, es selbst auf einfache Weise zu tun." –

+0

Toll, ich hoffe, Sie werden es mögen, in der Tat bin ich Gensons Autor =) – eugen

0

flexJson kann Ihnen auch helfen, das gleiche zu tun. Hier

ist ein Beispiel kopiert von FlexJson Doc

Die deserializeInto Funktion der Zeichenfolge und der Bezug auf bestehende Aufgabe übernimmt.

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); 

Beachten Sie, dass die in p zurückgegebene Referenz dieselbe ist wie charlieClone nur mit aktualisierten Werten.

0

Ich habe Jackson + Spring DataBinder verwendet, um so etwas zu erreichen. Dieser Code behandelt Arrays, aber keine verschachtelten Objekte.

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

immer in eine Dummy-Objekt und Verwendung Reflexion laden konnte die Daten zu übertragen. Wenn Ihr Herz nur mit gson

Beispiel eingestellt ist. unter der Annahme, dieser Code ist in dem Objekt, das Sie Daten in

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; 
} 

1

kopieren möchten Wenn Sie Spring Framework verwenden Sie BeanUtils Bibliothek für diese Aufgabe verwenden kann. Deinserialisieren Sie Ihre json-Zeichenfolge zunächst normal und verwenden Sie dann BeanUtils, um dieses Objekt in ein übergeordnetes Objekt zu setzen. Er erwartet außerdem, dass der Variablenname des Objekts im übergeordneten Objekt festgelegt wird. Hier ist das Code-Snippet:

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

Danke. Ich habe Angst, dass dies nicht wirklich das tut, was ich beabsichtigt habe. Dies sieht so aus, als würde man ein Feld/eine Eigenschaft manuell setzen. –