Could not write JSON: Infinite recursion (StackOverflowError) (through reference
5302 ワード
jacksonの@JsonBackReferenceと@JsonManagedReference、および@JsonIgnoreは、オブジェクトに双方向参照が存在することによる無限再帰(infinite recursion)の問題を解決するために使用されます.これらの寸法は、プロパティまたは対応するget、setメソッドで使用できます.@JsonBackReferenceと@JsonManagedReference:この2つの寸法は通常ペアリングで使用され、通常は親子関係で使用されます.@JsonBackReference寸法の属性は、オブジェクトをjsonデータに変換しようとするシーケンス化(serialization)時に無視されます(つまり、結果のjsonデータにはその属性の内容が含まれていません).JsonManagedReference寸法の属性はシーケンス化されます.シーケンス化の場合,@JsonBackReferenceの役割は@JsonIgnoreに相当し,この場合@JsonManagedReferenceを持たなくてもよい.ただし、逆シーケンス化(deserialization、すなわちjsonデータをオブジェクトに変換)では、@JsonManagedReferenceがない場合、@JsonBackReferenceタグの属性(無視された親または子)は自動的に注入されません.@JsonManagedReferenceがある場合は、自動注入@JsonBackReferenceタグの属性が自動的に入力されます.@JsonIgnore:属性を直接無視し、無限再帰を解除します.シーケンス化または逆シーケンス化は無視されます.もちろんget,setメソッドに寸法を付けると,シーケンス化がgetメソッド,逆シーケンス化がsetメソッドに対応するように別々に制御できる.親子関係では、@JsonIgnoreは、@JsonBackReferenceと@JsonManagedReferenceとの最大の違いである無視された属性値(親または子)を逆シーケンス化すると自動的に注入しません.サンプルテストコード(逆シーケンス化後のTreeNode[readValue]のchildren内のparentに注意):TreeNode.java
JsonTest.java
参考:http://wiki.fasterxml.com/JacksonFeatureBiDirReferences jira:http://jira.codehaus.org/browse/JACKSON-235備考:jacksonバージョン:1.9.9 jacksonは2.0から@JsonIdentityInfoで無限再帰の問題を解決できるようですが、本人は検証していません.興味があれば、この文章の方法を研究することもできます.
http://www.linuxso.com/architecture/26599.html
import java.util.ArrayList;
import java.util.List;
import org.codehaus.jackson.annotate.JsonBackReference;
import org.codehaus.jackson.annotate.JsonManagedReference;
public class TreeNode {
String name;
@JsonBackReference
// @JsonIgnore
TreeNode parent;
@JsonManagedReference
List<TreeNode> children;
public TreeNode() {
}
public TreeNode(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public TreeNode getParent() {
return parent;
}
public void setParent(TreeNode parent) {
this.parent = parent;
}
public List<TreeNode> getChildren() {
return children;
}
public void setChildren(List<TreeNode> children) {
this.children = children;
}
public void addChild(TreeNode child) {
if (children == null)
children = new ArrayList<TreeNode>();
children.add(child);
}
}
JsonTest.java
import java.io.IOException;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
public class JsonTest {
static TreeNode node;
@BeforeClass
public static void setUp() {
TreeNode node1 = new TreeNode("node1");
TreeNode node2 = new TreeNode("node2");
TreeNode node3 = new TreeNode("node3");
TreeNode node4 = new TreeNode("node4");
TreeNode node5 = new TreeNode("node5");
TreeNode node6 = new TreeNode("node6");
node1.addChild(node2);
node2.setParent(node1);
node2.addChild(node3);
node3.setParent(node2);
node2.addChild(node4);
node4.setParent(node2);
node3.addChild(node5);
node5.setParent(node3);
node5.addChild(node6);
node6.setParent(node5);
node = node3;
}
@Test
public void test() throws JsonGenerationException, JsonMappingException, IOException {
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(node);
System.out.println(json);
TreeNode readValue = mapper.readValue(json, TreeNode.class);
System.out.println(readValue.getName());
}
@AfterClass
public static void tearDown() {
node = null;
}
}
参考:http://wiki.fasterxml.com/JacksonFeatureBiDirReferences jira:http://jira.codehaus.org/browse/JACKSON-235備考:jacksonバージョン:1.9.9 jacksonは2.0から@JsonIdentityInfoで無限再帰の問題を解決できるようですが、本人は検証していません.興味があれば、この文章の方法を研究することもできます.
http://www.linuxso.com/architecture/26599.html