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 
    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