使用GSON

时间:2015-09-26 06:54:59

标签: java javafx gson

我目前正在按照教程帮助我了解JavaFX的工作原理,在教程中他们正在构建一个小应用来管理人们的信息。本教程还使用XML进行加载/保存,但我不想使用XML并且想要使用JSON。我有一个使用PersonStringPropertyIntegerProperty的{​​{1}}模型。我的问题是,我不确定加载和保存它的最佳方法是什么,如果没有保存不必要的字段,也可以在没有Gson的情况下加载错误。

ObjectProperty

保存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; } } personData ObservableList的<{1}}

Person

这种保存方式目前会产生一个保存,其中包含许多不必要的字段,例如try (Writer writer = new FileWriter(file)) { new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create().toJson(personData, writer); } name等,可能是value

"firstName": "Hans"

现在,即使尝试使用Gson加载上面的字符串,也会产生错误[{ "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": {} }]

装载机

Failed to invoke public javafx.beans.property.StringProperty() with no args

我用谷歌搜索是否有可能使用Gson的getter和setter但是看起来不太可能,所以我不知道该做什么。

3 个答案:

答案 0 :(得分:15)

我知道我参加派对有点晚了,但这是为了未来的读者。

我遇到了完全相同的问题。我最后编写了一堆Gson TypeAdapter,每个JavaFX属性类型一个(ColorFont还有一个。)

我将它们全部收集在a lightweight library called FxGson(&lt; 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));

输出:

{
  "firstName": "Hans",
  "lastName": "Muster",
  "street": "some street",
  "postalCode": 1234,
  "city": "some city",
  "birthday": {
    "year": 1999,
    "month": 2,
    "day": 21
  }
}

答案 1 :(得分:2)

我遇到了与GSON和JavaFX Property Model相同的问题。我使用LinkedHashMap解决了它,如下所示: -

在您的模型类中: -

public Person(LinkedHashMap<String, Object> personData) {
    this.firstName = new SimpleStringProperty((String) personData.get("firstName"));
    this.lastName = new SimpleStringProperty((String) personData.get("lastName"));

    this.street = new SimpleStringProperty((String) personData.get("street"));
    this.postalCode = new SimpleIntegerProperty(((Double) personData.get("postalCode")).intValue());
    this.city = new SimpleStringProperty((String) personData.get("city"));

    String birthdayString = (String) personData.get("birthday");
    LocalDate date = LocalDate.parse(birthdayString ,DateTimeFormatter.ofPattern("yyy, mm, dd"));
    this.birthday = new SimpleObjectProperty<LocalDate>(date);
}

public LinkedHashMap<String, Object> getPersonData() {
    LinkedHashMap<String, Object> personData = new LinkedHashMap<>();

    personData.put("firstName", firstName.getValue());
    personData.put("lastName", lastName.getValue());
    personData.put("street", street.getValue());
    personData.put("postalCode", postalCode.getValue());
    personData.put("city", city.getValue());
    personData.put("birthday", birthday.getValue());

    return personData;
}

然后在装载机中: -

Gson gson = new Gson();
List<LinkedHashMap<String, Object>> persons = new Gson().fromJson(jsonData, new TypeToken<List<LinkedHashMap<String, Object>>>() {}.getType());

for(LinkedHashMap<String, Object> personData : persons) {
    Person person = new Person(personData);
}

转换为Json: -

LinkedHashMap<String, Object> personData = person.getPersonData();

String jsonData = new Gson().toJson(personData);

请注意,GSON将int值映射为double,因为它更通用,因此您需要先将邮件代码转换为double,然后从中获取int值,请参阅此问题以获取更多信息。

How to prevent Gson from expressing integers as floats

答案 2 :(得分:1)

GSON是否需要?

我在GSON遇到同样的问题并切换到Jackson。它有效:

ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.writeValueAsString(persons));