在序列化为 XML 文件的过程中,我遇到了无限循环问题。我正在使用 java.beans,并通过 XMLEncoder,尝试序列化三个类:类别、联系人和事件。不幸的是,我无法创建 XML 文件,因为 Contact 类包含一个 List events 字段,同样,Event 类也有一个 List contact 字段,在它们之间创建了相互引用。问题是 XMLEncoder 在尝试序列化所有内容时,陷入了 Contact 和 Event 类之间的引用循环,从而导致错误,因为它可能会无限期地继续下去。
序列化器:
public class XMLSerializer
{
public void encode(List<Category> categories, List<Event> events, List<Contact> contacts)
{
try (XMLEncoder xmlEncoder = new XMLEncoder(new BufferedOutputStream(new FileOutputStream("data/xml_files/data.xml"))))
{
xmlEncoder.setPersistenceDelegate(LocalDateTime.class, new LocalDateTimePersistenceDelegate());
xmlEncoder.setPersistenceDelegate(LocalTime.class, new LocalTimePersistenceDelegate());
List<Object> mergedList = new ArrayList<>();
mergedList.addAll(categories);
mergedList.addAll(events);
mergedList.addAll(contacts);
xmlEncoder.writeObject(mergedList);
}
catch (IOException e)
{
e.printStackTrace();
}
}
public class LocalDateTimePersistenceDelegate extends DefaultPersistenceDelegate
{
@Override
protected Expression instantiate(Object oldInstance, Encoder out)
{
LocalDateTime ldt = (LocalDateTime) oldInstance;
return new Expression(ldt, oldInstance.getClass(), "parse", new Object[] { ldt.toString() });
}
}
public class LocalTimePersistenceDelegate extends DefaultPersistenceDelegate
{
@Override
protected Expression instantiate(Object oldInstance, Encoder out)
{
LocalTime lt = (LocalTime) oldInstance;
return new Expression(lt, oldInstance.getClass(), "parse", new Object[] { lt.toString() });
}
}
}
型号:
public class Category implements Comparable<Category>
{
private int id;
private String name;
private String colorHex;
public Category()
{
}
@Override
public String toString()
{
return name;
}
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getColorHex()
{
return colorHex;
}
public void setColorHex(String colorHex)
{
this.colorHex = colorHex;
}
@Override
public int compareTo(Category o)
{
return this.name.compareTo(o.getName());
}
}
public class Event implements Comparable<Event>
{
private int id;
private String name;
private LocalDateTime date;
private LocalTime notifyOffset;
private String location;
private String description;
private Category category;
private List<Contact> contacts = new ArrayList<Contact>();
public Event()
{
}
@Override
public String toString()
{
String locationStr = location.isEmpty() ? "No location" : location;
String descriptionStr = description.isEmpty() ? "No description" : description;
String categoryName = category != null ? category.getName() : "No category";
return String.format("%s | %s | %s%n%s%n%s", name, getFormattedDate(), locationStr, descriptionStr, categoryName);
}
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public LocalDateTime getDate()
{
return date;
}
public void setDate(LocalDateTime date)
{
this.date = date;
}
public LocalTime getNotifyOffset()
{
return notifyOffset;
}
public void setNotifyOffset(LocalTime notifyOffset)
{
this.notifyOffset = notifyOffset;
}
public String getLocation()
{
return location;
}
public void setLocation(String location)
{
this.location = location;
}
public String getDescription()
{
return description;
}
public void setDescription(String description)
{
this.description = description;
}
public Category getCategory()
{
return category;
}
public void setCategory(Category category)
{
this.category = category;
}
public List<Contact> getContacts()
{
return Collections.unmodifiableList(contacts);
}
public void setContacts(List<Contact> contacts)
{
this.contacts = contacts;
for (Contact contact : contacts)
{
contact.addEvent(this);
}
}
public void addContact(Contact contact)
{
if (!this.contacts.contains(contact))
{
this.contacts.add(contact);
contact.addEvent(this);
}
}
public void removeContact(Contact contact)
{
if (this.contacts.contains(contact))
{
this.contacts.remove(contact);
contact.removeEvent(this);
}
}
public String getFormattedDate()
{
return this.date.format(DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm"));
}
public String getFormattedDateWithOffset()
{
LocalDateTime offsetDateTime = this.date.minusHours(notifyOffset.getHour()).minusMinutes(notifyOffset.getMinute());
return offsetDateTime.format(DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm"));
}
public LocalDateTime getDateWithOffset()
{
LocalDateTime offsetDateTime = this.date.minusHours(notifyOffset.getHour()).minusMinutes(notifyOffset.getMinute());
return offsetDateTime;
}
@Override
public int compareTo(Event o)
{
return this.date.compareTo(o.getDate());
}
}
public class Contact implements Comparable<Contact>
{
private int id;
private String firstName;
private String lastName;
private String phoneNumber;
private List<Event> events = new ArrayList<Event>();
public Contact()
{
}
@Override
public String toString()
{
return String.format("%s %s | %s", firstName, lastName, phoneNumber);
}
public int getId()
{
return id;
}
public void setId(int id)
{
this.id = id;
}
public String getFirstName()
{
return firstName;
}
public void setFirstName(String firstName)
{
this.firstName = firstName;
}
public String getLastName()
{
return lastName;
}
public void setLastName(String lastName)
{
this.lastName = lastName;
}
public String getPhoneNumber()
{
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber)
{
this.phoneNumber = phoneNumber;
}
public List<Event> getEvents()
{
return Collections.unmodifiableList(events);
}
public void setEvents(List<Event> events)
{
this.events = events;
for (Event event : events)
{
event.addContact(this);
}
}
public void addEvent(Event event)
{
if (!this.events.contains(event))
{
this.events.add(event);
event.addContact(this);
}
}
public void removeEvent(Event event)
{
if (this.events.contains(event))
{
this.events.remove(event);
event.removeContact(this);
}
}
@Override
public int compareTo(Contact o)
{
return this.firstName.compareTo(o.getFirstName());
}
}
我能够使用以下类生成 XML。
联系班级。
public class Contact implements Comparable<Contact> {
private int id;
private String firstName;
private String lastName;
private String phoneNumber;
// private List<Event> events = new ArrayList<Event>();
public Contact() {
}
public Contact(int id, String firstName, String lastName, String phoneNumber) {
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
this.phoneNumber = phoneNumber;
}
@Override
public String toString() {
return String.format("%s %s | %s", firstName, lastName, phoneNumber);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
// public List<Event> getEvents() {
// return Collections.unmodifiableList(events);
// }
//
// public void setEvents(List<Event> events) {
// this.events = events;
//
// for (Event event : events) {
// event.addContact(this);
// }
// }
// public void addEvent(Event event) {
// if (!this.events.contains(event)) {
// this.events.add(event);
// event.addContact(this);
// }
// }
//
// public void removeEvent(Event event) {
// if (this.events.contains(event)) {
// this.events.remove(event);
// event.removeContact(this);
// }
// }
@Override
public int compareTo(Contact o) {
return this.firstName.compareTo(o.getFirstName());
}
}
活动类
public class Event implements Comparable<Event> {
private int id;
private String name;
private LocalDateTime date;
private LocalTime notifyOffset;
private String location;
private String description;
private Category category;
private List<Contact> contacts = new ArrayList<Contact>();
public Event() {
}
public Event(int id, String name, LocalDateTime date, LocalTime notifyOffset, String location, String description, Category category, List<Contact> contacts) {
this.id = id;
this.name = name;
this.date = date;
this.notifyOffset = notifyOffset;
this.location = location;
this.description = description;
this.category = category;
this.contacts = contacts;
}
@Override
public String toString() {
String locationStr = location.isEmpty() ? "No location" : location;
String descriptionStr = description.isEmpty() ? "No description" : description;
String categoryName = category != null ? category.getName() : "No category";
return String.format("%s | %s | %s%n%s%n%s", name, getFormattedDate(), locationStr, descriptionStr, categoryName);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public LocalDateTime getDate() {
return date;
}
public void setDate(LocalDateTime date) {
this.date = date;
}
public LocalTime getNotifyOffset() {
return notifyOffset;
}
public void setNotifyOffset(LocalTime notifyOffset) {
this.notifyOffset = notifyOffset;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
public List<Contact> getContacts() {
return Collections.unmodifiableList(contacts);
}
// public void setContacts(List<Contact> contacts) {
// this.contacts = contacts;
//
// for (Contact contact : contacts) {
// contact.addEvent(this);
// }
// }
//
// public void addContact(Contact contact) {
// if (!this.contacts.contains(contact)) {
// this.contacts.add(contact);
// contact.addEvent(this);
// }
// }
//
// public void removeContact(Contact contact) {
// if (this.contacts.contains(contact)) {
// this.contacts.remove(contact);
// contact.removeEvent(this);
// }
// }
public String getFormattedDate() {
return this.date.format(DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm"));
}
public String getFormattedDateWithOffset() {
LocalDateTime offsetDateTime = this.date.minusHours(notifyOffset.getHour()).minusMinutes(notifyOffset.getMinute());
return offsetDateTime.format(DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm"));
}
public LocalDateTime getDateWithOffset() {
LocalDateTime offsetDateTime = this.date.minusHours(notifyOffset.getHour()).minusMinutes(notifyOffset.getMinute());
return offsetDateTime;
}
@Override
public int compareTo(Event o) {
return this.date.compareTo(o.getDate());
}
}
数据.xml
<?xml version="1.0" encoding="UTF-8"?>
<java version="17.0.9" class="java.beans.XMLDecoder">
<object class="java.util.ArrayList">
<void method="add">
<object class="com.example.stackoverflow_77889401.Category" id="Category0">
<void property="colorHex">
<string>blue</string>
</void>
<void property="id">
<int>1</int>
</void>
<void property="name">
<string>category 1</string>
</void>
</object>
</void>
<void method="add">
<object class="com.example.stackoverflow_77889401.Category">
<void property="colorHex">
<string>red</string>
</void>
<void property="id">
<int>2</int>
</void>
<void property="name">
<string>category 2</string>
</void>
</object>
</void>
<void method="add">
<object class="com.example.stackoverflow_77889401.Event">
<void property="category">
<object idref="Category0"/>
</void>
<void property="date">
<object class="java.time.LocalDateTime" method="parse">
<string>2024-01-27T01:14:01.848394</string>
</object>
</void>
<void property="description">
<string>desc 1</string>
</void>
<void property="id">
<int>1</int>
</void>
<void property="location">
<string>loc 1</string>
</void>
<void property="name">
<string>event 1</string>
</void>
<void property="notifyOffset">
<object class="java.time.LocalTime" method="parse">
<string>01:14:01.848394</string>
</object>
</void>
</object>
</void>
<void method="add">
<object class="com.example.stackoverflow_77889401.Contact">
<void property="firstName">
<string>halil</string>
</void>
<void property="id">
<int>1</int>
</void>
<void property="lastName">
<string>ural</string>
</void>
<void property="phoneNumber">
<string>55555555555</string>
</void>
</object>
</void>
<void method="add">
<object class="com.example.stackoverflow_77889401.Contact">
<void property="firstName">
<string>ceren</string>
</void>
<void property="id">
<int>2</int>
</void>
<void property="lastName">
<string>guney</string>
</void>
<void property="phoneNumber">
<string>55555555555</string>
</void>
</object>
</void>
</object>
</java>