使用GSON序列化JavaFX模型

Jos*_*a F 12 java javafx gson

我目前正在学习一个教程,以帮助我学习JavaFX的工作原理,在教程中他们正在构建一个小应用来管理人们的信息.本教程还使用XML进行加载/保存,但我不想使用XML并且想要使用JSON.我有一个Person使用的模型StringProperty,IntegerPropertyObjectProperty.我的问题是,我不确定加载和保存这个的最佳方法是什么,如果没有它保存不必要的字段,也加载没有Gson抛出错误.

import java.time.LocalDate;

import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;

/**
 * Model class for a Person.
 *
 * @author Marco Jakob
 */
public class Person {

    private final StringProperty firstName;

    private final StringProperty lastName;

    private final StringProperty street;

    private final IntegerProperty postalCode;

    private final StringProperty city;

    private final ObjectProperty<LocalDate> birthday;

    /**
     * Default constructor.
     */
    public Person() {
        this(null, null);
    }

    /**
     * Constructor with some initial data.
     * 
     * @param firstName
     * @param lastName
     */
    public Person(String firstName, String lastName) {
        this.firstName = new SimpleStringProperty(firstName);
        this.lastName = new SimpleStringProperty(lastName);

        // Some initial dummy data, just for convenient testing.
        this.street = new SimpleStringProperty("some street");
        this.postalCode = new SimpleIntegerProperty(1234);
        this.city = new SimpleStringProperty("some city");
        this.birthday = new SimpleObjectProperty<LocalDate>(LocalDate.of(1999, 2, 21));
    }

    public String getFirstName() {
        return firstName.get();
    }

    public void setFirstName(String firstName) {
        this.firstName.set(firstName);
    }

    public StringProperty firstNameProperty() {
        return firstName;
    }

    public String getLastName() {
        return lastName.get();
    }

    public void setLastName(String lastName) {
        this.lastName.set(lastName);
    }

    public StringProperty lastNameProperty() {
        return lastName;
    }

    public String getStreet() {
        return street.get();
    }

    public void setStreet(String street) {
        this.street.set(street);
    }

    public StringProperty streetProperty() {
        return street;
    }

    public int getPostalCode() {
        return postalCode.get();
    }

    public void setPostalCode(int postalCode) {
        this.postalCode.set(postalCode);
    }

    public IntegerProperty postalCodeProperty() {
        return postalCode;
    }

    public String getCity() {
        return city.get();
    }

    public void setCity(String city) {
        this.city.set(city);
    }

    public StringProperty cityProperty() {
        return city;
    }

    public LocalDate getBirthday() {
        return birthday.get();
    }

    public void setBirthday(LocalDate birthday) {
        this.birthday.set(birthday);
    }

    public ObjectProperty<LocalDate> birthdayProperty() {
        return birthday;
    }
}
Run Code Online (Sandbox Code Playgroud)

保存在那里personDataObservableListPerson小号

try (Writer writer = new FileWriter(file)) {
    new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create().toJson(personData, writer);
}
Run Code Online (Sandbox Code Playgroud)

节约的这种方式目前生产与节约很多喜欢不必要的字段中name,value等时也可能是"firstName": "Hans"

[{
    "firstName": {
        "name": "",
        "value": "Hans",
        "valid": true,
        "helper": {
            "observable": {}
        }
    },
    "lastName": {
        "name": "",
        "value": "Muster",
        "valid": true,
        "helper": {
            "observable": {}
        }
    },
    "street": {
        "name": "",
        "value": "some street",
        "valid": true
    },
    "postalCode": {
        "name": "",
        "value": 1234,
        "valid": true
    },
    "city": {
        "name": "",
        "value": "some city",
        "valid": true
    },
    "birthday": {}
}]
Run Code Online (Sandbox Code Playgroud)

现在,即使尝试使用Gson加载上面的字符串,也会产生错误Failed to invoke public javafx.beans.property.StringProperty() with no args.

装载机

Person[] persons;

try (Reader reader = new FileReader(file)) {
    persons = gson.fromJson(reader, Person[].class);
}

personData.clear();
personData.addAll(persons);
Run Code Online (Sandbox Code Playgroud)

我用谷歌搜索看看是否有可能使用Gson的getter和setter但是它似乎不太可能,所以我坚持做什么.

Jof*_*rey 16

我知道我有点迟到了,但这是为了未来的读者.

我有同样的问题.我最终编写了一堆Gson TypeAdapter,每个JavaFX属性类型一个(还有一些用于ColorFont).

我将它们全部收集在一个名为FxGson(<30kB)的轻量级库中.

现在,只需使用FxGson GsonBuilder,JavaFX POJO就会被序列化,就像它们的属性是简单值一样.Person在示例中使用该类:

Person p = new Person("Hans", "Muster");
Gson gson = FxGson.coreBuilder().setPrettyPrinting().disableHtmlEscaping().create();
System.out.println(gson.toJson(p));
Run Code Online (Sandbox Code Playgroud)

这输出:

{
  "firstName": "Hans",
  "lastName": "Muster",
  "street": "some street",
  "postalCode": 1234,
  "city": "some city",
  "birthday": {
    "year": 1999,
    "month": 2,
    "day": 21
  }
}
Run Code Online (Sandbox Code Playgroud)