2017-09-22 6 views
0

Ich habe mein Objekt implementiert PropertyChangeSupport, aber wenn ich aus einem JSON-String deserialize, wäre die Variable propertyChangeSupportnull, obwohl ich den Wert selbst initialisieren mit einem new PropertyChangeSupport(this) im Standardkonstruktor. Wie kann ich es mit Gson richtig initialisieren oder deserialisieren?Wie initialisiert PropertyChangeSupport beim Deserialisieren von JSON (Gson)?

Sagen, ich habe dieses Objekt:

public class Blah implements BlahInterface { 
    private PropertyChangeSupport propertyChangeSupport; 

    protected int id; 
    protected BlahType type; 

    public Blah() { 
     propertyChangeSupport = new PropertyChangeSupport(this); 
    } 

    public int getId() { 
     return id; 
    } 

    public void setId(int id) { 
     this.id = id; 
    } 

    public BlahType getType() { 
     return type; 
    } 

    public void setType(BlahType type) { 
     this.type = type; 
    } 

    public void addPropertyChangeListener(PropertyChangeListener listener) { 
     this.propertyChangeSupport.addPropertyChangeListener(listener); 
    } 

    public PropertyChangeListener[] getPropertyChangeListeners() { 
     return this.propertyChangeSupport.getPropertyChangeListeners(); 
    } 
} 

Ich habe auch versucht die new PropertyChangeSupport(this); direkt am Anfang setzen und nicht entweder gehen. Ich möchte vermeiden, manuell eine Funktion wie initializePropertyChangeSupport() machen und dann manuell nach Deserialisierung aufrufen, da das ein bisschen hässlich ist.

Was ich versuche zu tun:

JsonArray ja = json.get("blahs").getAsJsonArray(); 
ja.forEach(item -> { 
    Blah blah = BlahInterface.Parse(item.toString()); 
    // But here I can't addPropertyChangeListener because propertyChangeSupport is null 
    // vvvvvvvvvvvv 
    blah.addPropertyChangeListener(new PropertyChangeListener() { 

     @Override 
     public void propertyChange(PropertyChangeEvent evt) { 
      BlahState state = (BlahState) evt.getNewValue(); 
      Logger.debug("Property had been updated, " + state.toString()); 
     } 
    }); 
}); 

Das ist meine json Parsing-Funktion:

@SuppressWarnings("unchecked") 
public static <T extends Blah> T Parse(String json) { 
    Gson gson = new Gson(); 

    Blah t = new Blah(gson.fromJson(json, Blah.class)); 
    switch (t.getType()) { 
     case blahone: 
      return (T) gson.fromJson(json, BlahOne.class); 
     default: 
      return (T) t; 
    } 
}; 
+0

Wo feuern Sie die Benachrichtigungsmethode überall? –

+0

Wie können Sie einem Objekt auch einen Listener hinzufügen, bevor es existiert? Ich bin nicht genau klar, was ** Eigenschaft die Eigenschaft ändern Listener hören - was soll die * gebundene * Eigenschaft (en) dieser Klasse sein? Wenn es sich um die Eigenschaft 'id' handelt, muss die Setter-Methode die Benachrichtigungsmethoden des Support-Objekts aufrufen. –

+0

Ich füge meinen 'PropertyChangeListener' hinzu, nachdem ich mein JSON-Objekt deserialisiert habe, im Grunde bekomme ich einen JSON-String vom Server, dann deserialisiere ich es in mein' Blah' -Objekt und versuche dann, meinen 'PropertyChangeListener' hinzuzufügen . Das Problem ist, dass die Variable null ist, da sie nicht Teil der JSON-Zeichenfolge war, aber ich versuche, hässliche Hacks zu vermeiden ... – codenamezero

Antwort

0

Die Lösung für dieses Problem ist InstanceCreator<T> in meinem Objekt implementiert. Wenn also Gson versucht, das Objekt zu deserialisieren, würde es die createInstance-Funktion aufrufen, die wiederum ein korrektes Objekt mit der initialisierten PropertyChangeSupport-Variable zurückgibt. Beispiel-Code unten:

public class Blah implements InstanceCreator<Blah> { 
    private final transient PropertyChangeSupport pcs = new PropertyChangeSupport(this); 

    ... 

    public void addPropertyChangeListener(PropertyChangeListener listener) { 
     this.pcs.addPropertyChangeListener(listener); 
    } 

    public void removePropertyChangeListener(PropertyChangeListener listener) { 
     this.pcs.removePropertyChangeListener(listener); 
    } 

    @Override 
    public Blah createInstance(Type type) { 
     return new Blah(); 
    } 
} 

Hinweis: transiente Schlüsselwort gibt es auf dem pcs gerade so, dass Gson es während serialize überspringen würde sonst wäre Gson Ausnahme auslösen.

Verwandte Themen