简体   繁体   中英

How to initialize PropertyChangeSupport when deserializing from JSON (Gson)?

I have my object implemented the PropertyChangeSupport , but when I deserialize from a json string, the variable propertyChangeSupport would be null , despite I initialize the value myself with a new PropertyChangeSupport(this) in the default constructor. How can I initialize or deserializing it properly using Gson?

Say I have this object:

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

I also tried putting the new PropertyChangeSupport(this); directly at the beginning and is no go either. I kind a want to avoid manually making a function such as initializePropertyChangeSupport() and then call it manually after deserialization since that's kinda ugly.

What I'm trying to do:

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

This is my json parsing function:

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

The solution to this problem is to implements InstanceCreator<T> in my object. So that when Gson tries to deserialize the object, it would call the createInstance function which in turns returns a proper object with the PropertyChangeSupport variable initialized. Example code below:

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: transient keyword is there on the pcs just so that Gson would skip it during serialize otherwise Gson would throw exception.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM