【问题标题】:How to initialize PropertyChangeSupport when deserializing from JSON (Gson)?从 JSON(Gson)反序列化时如何初始化 PropertyChangeSupport?
【发布时间】:2017-09-22 18:30:21
【问题描述】:

我的对象实现了 PropertyChangeSupport,但是当我从 json 字符串反序列化时,变量 propertyChangeSupport 将是 null,尽管我自己在默认构造函数中使用 new PropertyChangeSupport(this) 初始化了值。如何使用 Gson 正确初始化或反序列化它?

假设我有这个对象:

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

我也尝试将new PropertyChangeSupport(this); 直接放在开头,但也不行。我有点想避免手动创建诸如initializePropertyChangeSupport() 之类的函数,然后在反序列化后手动调用它,因为这有点难看。

我正在尝试做的事情:

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

这是我的json解析函数:

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

【问题讨论】:

  • 你在哪里触发通知方法?
  • 另外,如何在对象存在之前为其添加监听器?我不清楚属性更改侦听器将要侦听的 what 属性——这个类的 bound 属性应该是什么?如果是id属性,那么setter方法需要调用支持对象的通知方法。
  • 我在反序列化我的 json 对象后添加了我的PropertyChangeListener,基本上我从服务器获取了一个 json 字符串,然后使用该数据,我将其反序列化为我的Blah 对象,然后尝试添加我的PropertyChangeListener 给它。问题是该变量为空,因为它不是 json 字符串的一部分,但我试图避免丑陋的黑客攻击......
  • 什么变量为空?请告诉更多细节并显示更多相关代码。
  • 你是说这里:Blah blah = BlahInterface.Parse(item.toString());blah 变量是null?同样,什么 为空?再说一次,你在 Blah 的什么地方调用了支持的 firePropertyChange(...) 方法?

标签: java gson json-deserialization propertychangesupport


【解决方案1】:

解决这个问题的方法是在我的对象中实现InstanceCreator&lt;T&gt;。因此,当 Gson 尝试反序列化对象时,它会调用 createInstance 函数,该函数反过来返回一个正确的对象,并初始化了 PropertyChangeSupport 变量。示例代码如下:

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

注意:transient 关键字在pcs 上只是为了让 Gson 在序列化期间跳过它,否则 Gson 会抛出异常。

【讨论】:

    猜你喜欢
    • 2015-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多