XML 文件序列化期间的无限循环 (java.beans)

问题描述 投票:0回答:1

在序列化为 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());
    }
}
java serialization encoding xml-serialization javabeans
1个回答
0
投票

我能够使用以下类生成 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>

© www.soinside.com 2019 - 2024. All rights reserved.