为什么我在使用 jackson 时会出现 stackoverflow 错误,即使使用 @JsonIgnoreProperties
Why do i get an stackoverflow error when using jackson even though using @JsonIgnoreProperties
我正在尝试将带有 jackson 的 DefaultMutableTreeNode 对象序列化为 json 字符串。因此,我需要使用一个混合抽象 class,它是 DefaultMutableTreeNode class 的一种代理。这可能是因为自引用字段,但我无法识别它们。
混音class:
@JsonIgnoreProperties(ignoreUnknown = true)
public abstract class DefaultMutableTreeNodeMixIn {
@JsonCreator
public DefaultMutableTreeNodeMixIn(@JsonProperty Object userObject) {};
@JsonCreator
public DefaultMutableTreeNodeMixIn(@JsonProperty Object userObject,
@JsonProperty boolean allowsChildren) {};
@JsonProperty("childCount")
abstract int getChildCount();
@JsonProperty("depth")
abstract int getDepth();
@JsonProperty("firstChild")
abstract TreeNode getFirstChild();
@JsonProperty("firstLeaf")
abstract DefaultMutableTreeNode getFirstLeaf();
@JsonProperty("lastChild")
abstract TreeNode getLastChild();
@JsonProperty("lastLeaf")
abstract DefaultMutableTreeNode getLastLeaf();
@JsonProperty("leafCount")
abstract int getLeafCount();
@JsonProperty("level")
abstract int getLevel();
@JsonProperty("nextLeaf")
abstract DefaultMutableTreeNode getNextLeaf();
@JsonProperty("nextNode")
abstract DefaultMutableTreeNode getNextNode();
@JsonProperty("nextSibling")
abstract DefaultMutableTreeNode getNextSibling();
@JsonProperty("parent")
abstract TreeNode getParent();
@JsonProperty("path")
abstract TreeNode[] getPath();
@JsonProperty("previousLeaf")
abstract DefaultMutableTreeNode getPreviousLeaf();
@JsonProperty("previousNode")
abstract DefaultMutableTreeNode getPreviousNode();
@JsonProperty("previousSibling")
abstract DefaultMutableTreeNode getPreviousSibling();
@JsonProperty("siblingCount")
abstract int getSiblingCount();
@JsonProperty("isLeaf")
abstract boolean isLeaf();
@JsonProperty("isRoot")
abstract boolean isRoot();
}
对象映射器:
ObjectMapper mapper = new ObjectMapper();
mapper.addMixIn(DefaultMutableTreeNode.class,DefaultMutableTreeNodeMixIn.class);
String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(serverFileTree);
System.out.println(json);
(serverFileTree 是 DefaultMutableTreeNode 类型的对象)
错误跟踪:
at com.fasterxml.jackson.databind.ser.std.ObjectArraySerializer.serializeContents(ObjectArraySerializer.java:252)
at com.fasterxml.jackson.databind.ser.std.ObjectArraySerializer.serialize(ObjectArraySerializer.java:213)
at com.fasterxml.jackson.databind.ser.std.ObjectArraySerializer.serialize(ObjectArraySerializer.java:22)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155) [...]
Caused by: java.lang.WhosebugError
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.access0(Unknown Source)
at java.net.URLClassLoader.run(Unknown Source)
at java.net.URLClassLoader.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:737)
... 1011 more
如 Jackson 的文档所述:https://fasterxml.github.io/jackson-annotations/javadoc/2.6/com/fasterxml/jackson/annotation/JsonProperty.html
public @interface JsonProperty
Marker annotation that can be used to define a non-static method as a
"setter" or "getter" for a logical property (depending on its
signature), or non-static object field to be used (serialized,
deserialized) as a logical property.
我确实认为您注释了不是 setter 或 getter 属性的方法。
例如:
@JsonProperty("previousNode")
abstract DefaultMutableTreeNode getPreviousNode();
这个方法好像不是得不到属性,而是在计算一个节点。尝试删除方法上的所有注释,看看是否可以解决问题。
当您开始遍历他们的 getter 方法时,class 会生成循环。要打破它们,您需要使用 JsonBackReference
注释。您的 mixin
可能如下所示:
@JsonIgnoreProperties(ignoreUnknown = true)
abstract class DefaultMutableTreeNodeMixIn {
@JsonCreator
public DefaultMutableTreeNodeMixIn(@JsonProperty Object userObject) {
}
@JsonCreator
public DefaultMutableTreeNodeMixIn(@JsonProperty Object userObject, @JsonProperty boolean allowsChildren) {
}
@JsonProperty("childCount")
abstract int getChildCount();
@JsonProperty("depth")
abstract int getDepth();
@JsonProperty("firstChild")
@JsonBackReference
abstract TreeNode getFirstChild();
@JsonProperty("firstLeaf")
@JsonBackReference
abstract DefaultMutableTreeNode getFirstLeaf();
@JsonProperty("lastChild")
@JsonBackReference
abstract TreeNode getLastChild();
@JsonProperty("lastLeaf")
@JsonBackReference
abstract DefaultMutableTreeNode getLastLeaf();
@JsonProperty("leafCount")
abstract int getLeafCount();
@JsonProperty("level")
abstract int getLevel();
@JsonProperty("nextLeaf")
abstract DefaultMutableTreeNode getNextLeaf();
@JsonProperty("nextNode")
abstract DefaultMutableTreeNode getNextNode();
@JsonProperty("nextSibling")
abstract DefaultMutableTreeNode getNextSibling();
@JsonProperty("parent")
abstract TreeNode getParent();
@JsonProperty("path")
@JsonBackReference
abstract TreeNode[] getPath();
@JsonProperty("previousLeaf")
abstract DefaultMutableTreeNode getPreviousLeaf();
@JsonProperty("previousNode")
abstract DefaultMutableTreeNode getPreviousNode();
@JsonProperty("previousSibling")
abstract DefaultMutableTreeNode getPreviousSibling();
@JsonProperty("siblingCount")
abstract int getSiblingCount();
@JsonProperty("isLeaf")
abstract boolean isLeaf();
@JsonProperty("isRoot")
abstract boolean isRoot();
}
但可能最好和最 OOP
的方法是创建新的 POJO
表示您的树准备好序列化并且没有循环。
我正在尝试将带有 jackson 的 DefaultMutableTreeNode 对象序列化为 json 字符串。因此,我需要使用一个混合抽象 class,它是 DefaultMutableTreeNode class 的一种代理。这可能是因为自引用字段,但我无法识别它们。
混音class:
@JsonIgnoreProperties(ignoreUnknown = true)
public abstract class DefaultMutableTreeNodeMixIn {
@JsonCreator
public DefaultMutableTreeNodeMixIn(@JsonProperty Object userObject) {};
@JsonCreator
public DefaultMutableTreeNodeMixIn(@JsonProperty Object userObject,
@JsonProperty boolean allowsChildren) {};
@JsonProperty("childCount")
abstract int getChildCount();
@JsonProperty("depth")
abstract int getDepth();
@JsonProperty("firstChild")
abstract TreeNode getFirstChild();
@JsonProperty("firstLeaf")
abstract DefaultMutableTreeNode getFirstLeaf();
@JsonProperty("lastChild")
abstract TreeNode getLastChild();
@JsonProperty("lastLeaf")
abstract DefaultMutableTreeNode getLastLeaf();
@JsonProperty("leafCount")
abstract int getLeafCount();
@JsonProperty("level")
abstract int getLevel();
@JsonProperty("nextLeaf")
abstract DefaultMutableTreeNode getNextLeaf();
@JsonProperty("nextNode")
abstract DefaultMutableTreeNode getNextNode();
@JsonProperty("nextSibling")
abstract DefaultMutableTreeNode getNextSibling();
@JsonProperty("parent")
abstract TreeNode getParent();
@JsonProperty("path")
abstract TreeNode[] getPath();
@JsonProperty("previousLeaf")
abstract DefaultMutableTreeNode getPreviousLeaf();
@JsonProperty("previousNode")
abstract DefaultMutableTreeNode getPreviousNode();
@JsonProperty("previousSibling")
abstract DefaultMutableTreeNode getPreviousSibling();
@JsonProperty("siblingCount")
abstract int getSiblingCount();
@JsonProperty("isLeaf")
abstract boolean isLeaf();
@JsonProperty("isRoot")
abstract boolean isRoot();
}
对象映射器:
ObjectMapper mapper = new ObjectMapper();
mapper.addMixIn(DefaultMutableTreeNode.class,DefaultMutableTreeNodeMixIn.class);
String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(serverFileTree);
System.out.println(json);
(serverFileTree 是 DefaultMutableTreeNode 类型的对象)
错误跟踪:
at com.fasterxml.jackson.databind.ser.std.ObjectArraySerializer.serializeContents(ObjectArraySerializer.java:252)
at com.fasterxml.jackson.databind.ser.std.ObjectArraySerializer.serialize(ObjectArraySerializer.java:213)
at com.fasterxml.jackson.databind.ser.std.ObjectArraySerializer.serialize(ObjectArraySerializer.java:22)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155) [...]
Caused by: java.lang.WhosebugError
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.access0(Unknown Source)
at java.net.URLClassLoader.run(Unknown Source)
at java.net.URLClassLoader.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:737)
... 1011 more
如 Jackson 的文档所述:https://fasterxml.github.io/jackson-annotations/javadoc/2.6/com/fasterxml/jackson/annotation/JsonProperty.html
public @interface JsonProperty
Marker annotation that can be used to define a non-static method as a "setter" or "getter" for a logical property (depending on its signature), or non-static object field to be used (serialized, deserialized) as a logical property.
我确实认为您注释了不是 setter 或 getter 属性的方法。
例如:
@JsonProperty("previousNode")
abstract DefaultMutableTreeNode getPreviousNode();
这个方法好像不是得不到属性,而是在计算一个节点。尝试删除方法上的所有注释,看看是否可以解决问题。
当您开始遍历他们的 getter 方法时,class 会生成循环。要打破它们,您需要使用 JsonBackReference
注释。您的 mixin
可能如下所示:
@JsonIgnoreProperties(ignoreUnknown = true)
abstract class DefaultMutableTreeNodeMixIn {
@JsonCreator
public DefaultMutableTreeNodeMixIn(@JsonProperty Object userObject) {
}
@JsonCreator
public DefaultMutableTreeNodeMixIn(@JsonProperty Object userObject, @JsonProperty boolean allowsChildren) {
}
@JsonProperty("childCount")
abstract int getChildCount();
@JsonProperty("depth")
abstract int getDepth();
@JsonProperty("firstChild")
@JsonBackReference
abstract TreeNode getFirstChild();
@JsonProperty("firstLeaf")
@JsonBackReference
abstract DefaultMutableTreeNode getFirstLeaf();
@JsonProperty("lastChild")
@JsonBackReference
abstract TreeNode getLastChild();
@JsonProperty("lastLeaf")
@JsonBackReference
abstract DefaultMutableTreeNode getLastLeaf();
@JsonProperty("leafCount")
abstract int getLeafCount();
@JsonProperty("level")
abstract int getLevel();
@JsonProperty("nextLeaf")
abstract DefaultMutableTreeNode getNextLeaf();
@JsonProperty("nextNode")
abstract DefaultMutableTreeNode getNextNode();
@JsonProperty("nextSibling")
abstract DefaultMutableTreeNode getNextSibling();
@JsonProperty("parent")
abstract TreeNode getParent();
@JsonProperty("path")
@JsonBackReference
abstract TreeNode[] getPath();
@JsonProperty("previousLeaf")
abstract DefaultMutableTreeNode getPreviousLeaf();
@JsonProperty("previousNode")
abstract DefaultMutableTreeNode getPreviousNode();
@JsonProperty("previousSibling")
abstract DefaultMutableTreeNode getPreviousSibling();
@JsonProperty("siblingCount")
abstract int getSiblingCount();
@JsonProperty("isLeaf")
abstract boolean isLeaf();
@JsonProperty("isRoot")
abstract boolean isRoot();
}
但可能最好和最 OOP
的方法是创建新的 POJO
表示您的树准备好序列化并且没有循环。