Сериализация модели JavaFX с помощью GSON
в настоящее время я следую учебнику, чтобы помочь мне узнать, как работает JavaFX, и в учебнике они строят небольшое приложение для управления информацией о людях. Учебник также использует XML для загрузки / сохранения, но я не хочу использовать XML и хотел бы использовать JSON. У меня есть Person
модель, которая использует StringProperty
, IntegerProperty
и ObjectProperty
. Моя проблема в том, что я не совсем уверен, что лучший способ загрузить и сохранить это было бы без сохранения ненужных полей, а также загрузки без 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;
}
}
сохранения, где personData
это ObservableList
of Person
s
try (Writer writer = new FileWriter(file)) {
new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create().toJson(personData, writer);
}
этот способ сохранения в настоящее время создает сохранение с большим количеством ненужных полей, таких как 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": {}
}]
теперь, когда даже пытается загрузить строку выше с помощью 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);
я погуглил, чтобы узнать, можно ли использовать геттеры и сеттеры с Gson, но это не кажется возможным, поэтому я застрял на том, что делать.
3 ответов
Я знаю, что немного опоздал на вечеринку, но это для будущих читателей.
у меня была точно такая же проблема. Я закончила кучу Дсын TypeAdapter
s, по одному для каждого типа свойств JavaFX (и еще несколько для Color
и Font
).
я собрал их всех в легкая библиотека под названием FxGson (
теперь, просто используя fxgson's GsonBuilder
, POJOs JavaFX будут сериализованы, как если бы их свойства были простыми значениями.
С помощью the 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
}
}
я столкнулся с той же проблемой с моделью свойств Gson и JavaFX.И я решил его с помощью 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 в два раза, поскольку оно более общее, поэтому вам нужно сначала ввести почтовый индекс, а затем получить значение int из него. информация.
как предотвратить Gson от выражения целых чисел в виде поплавков
являются ли Gson требованием?
У меня такая же проблема с GSON и переключилась на Джексон. Работает:
ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.writeValueAsString(persons));