- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在编写一个简单的预算程序,其中有一个预算类和一系列类别类。每个类别类可以有子类别类。当我尝试使用 JAXB 将数据保存到 XML 文件时,出现错误com.sun.istack.internal.SAXException2:在对象图中检测到循环。这将导致无限深的XML
我搜索了该错误,发现它是由父子关系引起的,其中父级引用子级,子级引用父级。大多数答案是使用@XMLTransient。
我的问题是我的类别类既不引用预算父项,也不引用类别父项(如果存在)。
我是 JAXB 新手,但不是 Java。我使用这个应用程序作为 JAXB 和 JavaFX 的学习体验。
以下是我的预算和类别类别。
package budget.model;
import java.time.LocalDate;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import budget.util.BudgetProperties.DayOfWeek;
import budget.util.LocalDateAdapter;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
@XmlRootElement(name = "budget")
public class Budget {
// default to Sunday
ObjectProperty<DayOfWeek> startOfWeek = new SimpleObjectProperty<DayOfWeek>(DayOfWeek.SUNDAY);
ObjectProperty<LocalDate> startDate = new SimpleObjectProperty<LocalDate>();
IntegerProperty daysBeyondWeek = new SimpleIntegerProperty(3);
IntegerProperty numberOfWeeks = new SimpleIntegerProperty();
ObservableList<Category> categories = FXCollections.observableArrayList();
// startOfWeek
public DayOfWeek getStartOfWeek() {
return this.startOfWeek.getValue();
}
public void setStartOfWeek(DayOfWeek startOfWeek) {
this.startOfWeek.set(startOfWeek);
}
public ObjectProperty<DayOfWeek> startOfWeekProperty() {
return this.startOfWeek;
}
// startDate
@XmlJavaTypeAdapter(LocalDateAdapter.class)
public LocalDate getStartDate() {
return this.startDate.getValue();
}
public void setStartDate(LocalDate startDate){
this.startDate.set(startDate);
}
public ObjectProperty<LocalDate> startDateProperty() {
return this.startDate;
}
// daysBeyondWeek
public Integer getDaysBeyondWeek() {
return this.daysBeyondWeek.getValue();
}
public void setDaysBeyondWeek(Integer daysBeyondWeek) {
this.daysBeyondWeek.set(daysBeyondWeek);
}
public IntegerProperty daysBeyondWeekProperty() {
return this.daysBeyondWeek;
}
// numberOFWeeks
public Integer getNumberOfWeeks() {
return this.numberOfWeeks.getValue();
}
public void setNumberOfWeeks(Integer numberOfWeeks) {
this.numberOfWeeks.set(numberOfWeeks);
}
public IntegerProperty numberOfWeeksProperty() {
return numberOfWeeks;
}
// categories
public ObservableList<Category> getCategories () {
return categories;
}
public void setCategories(ObservableList<Category> categories) {
this.categories = categories;
}
public ObservableList<Category> categoriesProperty () {
return categories;
}
}
package budget.model;
import java.time.LocalDate;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import budget.util.BudgetProperties.RepeatFrequency;
import budget.util.LocalDateAdapter;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
public class Category {
StringProperty name = new SimpleStringProperty("");
ObservableList<Category> children = FXCollections.observableArrayList();
StringProperty comments = new SimpleStringProperty("");
ObjectProperty<RepeatFrequency> repeatFrequency = new SimpleObjectProperty<RepeatFrequency>();
ObjectProperty<LocalDate> dueDate = new SimpleObjectProperty<LocalDate>();
DoubleProperty budgetAmount = new SimpleDoubleProperty();
DoubleProperty actualAmount = new SimpleDoubleProperty();
// name
public String getName() {
return name.getValue();
}
public void setName(String name) {
this.name.set(name);
}
public StringProperty nameProperty() {
return name;
}
// children
public ObservableList<Category> getChildren() {
return children;
}
public void setChildren(ObservableList<Category> children) {
this.children.setAll(children);
}
public void addChild(Category category) {
this.children.add(category);
}
// isParent
public Boolean isParent() {
// return this.parent.getValue();
if (children == null || children.isEmpty() || children.size() == 0) {
return false;
} else {
return true;
}
}
// comments
public String getComments() {
return comments.getValue();
}
public void setComments(String comments) {
this.comments.set(comments);
}
public StringProperty commentsProperty() {
return comments;
}
// repeatFrequency
public RepeatFrequency getRepeatFrequency() {
return this.repeatFrequency.getValue();
}
public void setRepeatFrequency(RepeatFrequency repeatFrequency) {
this.repeatFrequency.set(repeatFrequency);
}
public ObjectProperty<RepeatFrequency> repeatFrequencyProperty() {
return this.repeatFrequency;
}
// dueDate
@XmlJavaTypeAdapter(LocalDateAdapter.class)
public LocalDate getDueDate() {
return this.dueDate.getValue();
}
public void setDueDate(LocalDate dueDate) {
this.dueDate.set(dueDate);
}
public ObjectProperty<LocalDate> dueDateProperty() {
return this.dueDate;
}
// budgetAmount
public Double getBudgetAmount() {
return this.budgetAmount.getValue();
}
public void setBudgetAmount(Double budgetAmount) {
this.budgetAmount.set(budgetAmount);
}
public DoubleProperty budgetAmountProperty() {
return this.budgetAmount;
}
// actualAmount
public Double getActualAmount() {
return this.actualAmount.getValue();
}
public void setActualAmount(Double actualAmount) {
this.actualAmount.set(actualAmount);
}
public DoubleProperty actualAmountProperty() {
return this.actualAmount;
}
}
还有另一个类处理编码。该类的函数如下
public void saveBudgetData(Budget budget) {
File file = new File(path + BUDGET_FILE);
try {
JAXBContext context = JAXBContext
.newInstance(Budget.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
// Marshalling and saving XML to the file.
m.marshal(budget, file);
} catch (Exception e) { // catches ANY exception
logger.error("exception: ", e);
Alert alert = new Alert(AlertType.ERROR);
alert.setTitle("Error");
alert.setHeaderText("Could not save data");
alert.setContentText("Could not save data to file:\n" + file.getPath());
alert.showAndWait();
}
}
我理解这是类别之间的递归关系。这就是它所提示的吗?我在搜索中没有看到这种情况。
谢谢。
清理了预算和类别类别
package budget.model;
import java.time.LocalDate;
import java.util.ArrayList;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import budget.util.BudgetProperties.DayOfWeek;
import budget.util.LocalDateAdapter;
@XmlRootElement(name = "budget")
public class BudgetNoFX {
// default to Sunday
DayOfWeek startOfWeek = DayOfWeek.SUNDAY;
// default to now
LocalDate startDate = LocalDate.now();
// number of days beyond week end to include in list of due bills
// default to 3
Integer daysBeyondWeek = new Integer(3);
Integer numberOfWeeks = new Integer(0);
ArrayList<CategoryNoFX> categories = new ArrayList<CategoryNoFX>();
// startOfWeek
public DayOfWeek getStartOfWeek() {
return this.startOfWeek;
}
public void setStartOfWeek(DayOfWeek startOfWeek) {
this.startOfWeek = startOfWeek;
}
// startDate
@XmlJavaTypeAdapter(LocalDateAdapter.class)
public LocalDate getStartDate() {
return this.startDate;
}
public void setStartDate(LocalDate startDate){
this.startDate = startDate;
}
// daysBeyondWeek
public Integer getDaysBeyondWeek() {
return this.daysBeyondWeek;
}
public void setDaysBeyondWeek(Integer daysBeyondWeek) {
this.daysBeyondWeek = daysBeyondWeek;
}
// numberOFWeeks
public Integer getNumberOfWeeks() {
return this.numberOfWeeks;
}
public void setNumberOfWeeks(Integer numberOfWeeks) {
this.numberOfWeeks = numberOfWeeks;
}
// categories
public ArrayList<CategoryNoFX> getCategories () {
return categories;
}
public void setCategories(ArrayList<CategoryNoFX> categories) {
this.categories = categories;
}
}
package budget.model;
import java.time.LocalDate;
import java.util.ArrayList;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import budget.util.BudgetProperties.RepeatFrequency;
import budget.util.LocalDateAdapter;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
public class CategoryNoFX {
public static final String ROOT_CATEGORY = "ROOT";
String name = new String("");
ArrayList<CategoryNoFX> children = new ArrayList<CategoryNoFX>();
String comments = new String("");
// default to monthly
RepeatFrequency repeatFrequency = RepeatFrequency.MONTHLY;
LocalDate dueDate = LocalDate.now();
Double budgetAmount = new Double(0);
Double actualAmount = new Double(0);
// name
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// children
public ArrayList<CategoryNoFX> getChildren() {
return children;
}
public void setChildren(ArrayList<CategoryNoFX> children) {
this.children = children;
}
public void addChild(CategoryNoFX category) {
this.children.add(category);
}
// isParent
public Boolean isParent() {
if (children == null || children.isEmpty() || children.size() == 0) {
return false;
} else {
return true;
}
}
// comments
public String getComments() {
return comments;
}
public void setComments(String comments) {
this.comments = comments;
}
// repeatFrequency
public RepeatFrequency getRepeatFrequency() {
return this.repeatFrequency;
}
public void setRepeatFrequency(RepeatFrequency repeatFrequency) {
this.repeatFrequency = repeatFrequency;
}
// dueDate
@XmlJavaTypeAdapter(LocalDateAdapter.class)
public LocalDate getDueDate() {
return this.dueDate;
}
public void setDueDate(LocalDate dueDate) {
this.dueDate = dueDate;
}
// budgetAmount
public Double getBudgetAmount() {
return this.budgetAmount;
}
public void setBudgetAmount(Double budgetAmount) {
this.budgetAmount = budgetAmount;
}
// actualAmount
public Double getActualAmount() {
return this.actualAmount;
}
public void setActualAmount(Double actualAmount) {
this.actualAmount = actualAmount;
}
}
我更新了 saveBudgetData 函数以使用新的预算类别
public void saveBudgetData(BudgetNoFX budget) {
File file = new File(path + BUDGET_FILE);
try {
JAXBContext context = JAXBContext
.newInstance(BudgetNoFX.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
// Marshalling and saving XML to the file.
m.marshal(budget, file);
} catch (Exception e) { // catches ANY exception
logger.error("exception: ", e);
Alert alert = new Alert(AlertType.ERROR);
alert.setTitle("Error");
alert.setHeaderText("Could not save data");
alert.setContentText("Could not save data to file:\n" + file.getPath());
alert.showAndWait();
}
}
最佳答案
我有点尴尬。我知道你必须小心递归,这就是我的问题。
在构建用户界面之前,我对一些值进行了硬编码 - 创建了预算并添加了一些类别。我应该发布该代码。我小时候就将其中一个类别设置为它自己。
Category food = new Category();
food.setName("Food");
categories.add(food);
Category groceries = new Category();
groceries.setBudgetAmount(new Double(120));
groceries.setName("Groceries");
// groceries.setParentCategory("Food");
groceries.setRepeatFrequency(RepeatFrequency.WEEKLY);
food.addChild(food); <-- problem line
一旦我将有问题的行修复为
food.addChild(groceries);
它开始工作了。
我通过注释掉 XML 的保存函数找到了它,而是将我的预算对象写到屏幕上。
我最近读过这个教程:http://code.makery.ch/library/javafx-8-tutorial/并构建了另一个简单的应用程序。这就是 LocalDateAdapter 类的来源。在第 5 部分中,他解释了 jaxb 和列表。我对代码进行了一些更改以更好地处理我的列表,并且我得到了令我满意的 xml 输出。
感谢您花时间查看我的代码并帮助我。如果我完成了这件事,也许我会将应用程序/代码发布到互联网上。我以前从未这样做过,但不知道最好的地方。
再次感谢。克里斯
关于java - JAXB 这会导致无限深的XML,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39800730/
拿这个: var lists:{ item1:{} ,item2:{} ,item3:{} ,item4:{} } 由于它基本上是空的,我想要一个函数(可能但不一定是 _lodash
我想更改 ng bootstrap 分页组件的样式并在 Angular 6 应用程序中使用 /deep/ 链接。以下代码工作正常,但控制台显示警告,指出该代码已被弃用。 那么,我应该如何更改它以消除警
使用 webcomponents,您可以使用 /deep/ 定位 shadowdom 的内部元素,在我尝试使用事件委托(delegate)之前它工作正常。 一个常规的点击功能将起作用: $('html
在 Swift 中,我试图实现一个单词 Trie,使用文字表示作为一系列嵌套的 NSObject。这是 Trie。 let GEENITRIE:NSObject = [ "i":[
运行 npm update 更新 package.json 中列出的项目;但是,这些项目的依赖关系仍然过时。 明显的解决方法是再次运行 npm update。有时我需要运行它 3 次以上才能使 npm
我创建了 2 级嵌套 linq 查询: var data = (from p in Departments join e in Employees on p.Id equals
首先是代码 #include typedef wchar_t* BSTR; wchar_t hello[] = L"Hello"; class _bstr_t { public: opera
我要编写一个 lisp 程序来生成十六进制数的实际值。我已经编写了一个函数,但似乎出现了 stackoverflow(深度)错误。我想知道是否有人可以指出我的错误或指导我朝着正确的方向前进。 如果没有
我想将每种类型都转换为boolean 或object type CastDeep = { [P in keyof T]: K extends K[] ? K[] : T[P] ex
我刚刚发现自己在写这个: fn init_timestamps(dir: &PathBuf, file_timestamps: &'static HashMap) { match fs::re
我有一个现有的 pybind11::array_t,需要进行复制构造。 pybind11 中是否有一个函数允许我对 array_t 进行深度复制? 我知道我可以创建一个新的 array_t,适当调整大
引用http://www.devx.com/tips/Tip/13291 ,它说我可以使用 memcpy 来复制由 sizeof() 确定的大小,但是,数组不是指向指针吗? 除了遍历数组,如何使用 m
我有多个成员(member),每个成员(member)都有一条记录,其中包含几个备注字段: Member ID Entry A Entry B 1 [memo t
$watchCollection 是否能够忽略对以 $ 开头的属性的更改?使用深度 $watch 时已经存在此行为,因为它依赖于 angular.equals 进行比较。 理想情况下,$watchCo
我有一个带有复杂键的 map - 例如,二维数组: m := make(map[[2][3]int]int) 当我在映射中插入一个新键时,Go 是否会对该键进行深度复制? a := [2][3]int
我需要查询如下所述的三个表。我了解简单的 JOIN,但是这个有点超出我的水平。 courses 有两列 id (PK) 和 courseTitle(示例 id 1,courseTitle 物理) cl
我有一个对象,它是 Realm 的 Object 子类,并且符合 Codable 以便在与 API 对话时与 JSON 相互转换。 如何利用 Codable 协议(protocol)进行深度复制(包括
我是一名优秀的程序员,十分优秀!