2017-09-22 7 views
0

J'ai mon objet implémenté le PropertyChangeSupport, mais quand je désérialise d'une chaîne json, la variable propertyChangeSupport serait null, malgré que j'initialise la valeur moi-même avec un new PropertyChangeSupport(this) dans le constructeur par défaut. Comment puis-je l'initialiser ou le désérialiser correctement en utilisant Gson?Comment initialiser PropertyChangeSupport lors de la désérialisation à partir de JSON (Gson)?

Dire que j'ai cet objet:

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

J'ai essayé aussi de mettre le new PropertyChangeSupport(this); directement au début et est d'aller pas non plus. Je voudrais juste éviter d'effectuer manuellement une fonction telle que initializePropertyChangeSupport() puis l'appeler manuellement après la désérialisation car c'est plutôt moche.

Ce que je suis en train de faire:

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

Ceci est mon JSON fonction d'analyse syntaxique:

@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

Où lancez-vous la méthode de notification n'importe où? –

+0

Comment pouvez-vous ajouter un écouteur à un objet avant qu'il n'existe? Je ne suis pas clair exactement ** quelle ** propriété les auditeurs de changement de propriété écouteront - ce qui est censé être la * bound * propriété (s) de cette classe? Si c'est la propriété 'id', alors la méthode setter doit appeler les méthodes de notification de l'objet support. –

+0

J'ajoute mon 'PropertyChangeListener' après avoir désérialisé mon objet json, en gros je reçois une chaîne json du serveur, puis avec ces données, je le désérialise dans mon objet' Blah', puis j'essaye d'ajouter mon 'PropertyChangeListener' . Le problème est que la variable est nulle car elle ne faisait pas partie de la chaîne JSON, mais j'essaie d'éviter les hacks moche ... – codenamezero

Répondre

0

La solution à ce problème est d'en œuvre InstanceCreator<T> dans mon objet. Ainsi, lorsque Gson essaie de désérialiser l'objet, il appelle la fonction createInstance qui à son tour renvoie un objet approprié avec la variable PropertyChangeSupport initialisée. Exemple de code ci-dessous:

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

Note: mot-clé transitoire est là sur le pcs juste pour que Gson sauterait pendant serialize autrement Gson jetterait exception.