2012-04-17 38 views
24

我使用Jackson庫將我的pojo對象序列化爲JSON表示形式。 比如我有A類和B類:傑克遜JSON序列化,按級別定義遞歸規避

class A { 
    private int id; 
    private B b; 

    constructors... 
    getters and setters 
} 

class B { 
    private int ind; 
    private A a; 

    constructors... 
    getters and setters 
} 

如果我想從序列化類A的對象有一定的可能性得到遞歸而這是序列化。我知道我可以通過使用@JsonIgnore來阻止它。

是否有可能通過深度級別來限制序列化?

例如,如果該電平爲2,則串行化會是這樣的:

  • 序列化,級別= 0(0 < 2 OK) - >序列
  • 連載AB,級別= 1 (1 < 2 OK) - >序列
  • 連載ABA,級別= 2(2 < 2不是真的) - > 停止

提前致謝。

+0

您是否能夠最終找到一種方法來指定您希望序列化發生的遞歸深度? – 2013-12-21 05:47:42

+0

我通過在被引用的實體上使用@JsonIgnore來解決(使用遞歸),所以我簡單地不包括在序列化中。當我需要特定的實例時,我已經擁有了該ID,並且我額外撥打了該實例。我沒有使用一般的解決方案,幸運的是我有幾個案例。 – 2013-12-25 13:23:46

回答

4

沒有支持基於級別的忽略。

但是,您可以讓傑克遜用2.0處理循環引用,有關如何使用@JsonIdentityInfo的說明,請參閱例如「Jackson 2.0 released」。

20

我最近遇到了類似的問題: - 傑克遜serialization of entities with birectional relationships(避免週期)

因此,解決辦法是升級到傑克遜2.0,並添加類以下注釋:

@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, 
        property = "@id") 
public class SomeEntityClass ... 

這工作完全。

+8

這真是不錯的方法。但是你知道一種限制圖形深度的方法嗎? – oak 2014-01-06 09:49:49

0

對於某些情況,您可以使用保持最大深度的線程局部整數來限制序列化深度。看到這個answer

1

如果你想限制自己只有一個級別(即:你去到當前的對象,而不是進一步的孩子),有一個@JsonView的簡單解決方案。

在每一個領域是另一個對象的鏈接,與當前的類作爲您的觀點將其標註爲:

class A { 
    private int id; 
    @JsonView(A.class) private B b; 

    constructors... 
    getters and setters 
} 

class B { 
    private int ind; 
    @JsonView(B.class) private A a; 

    constructors... 
    getters and setters 
} 

然後,序列化時,使用對象類作爲您的視圖。序列化的一個實例,將使這樣的事情:

{ 
    id: 42, 
    b: { 
    id: 813 
    } 
} 

確保DEFAULT_VIEW_INCLUSION設置爲true,或沒有@JsonView註釋字段將不會被渲染。另外,您也可以標註與@JsonView所有其他領域使用Object類,或任何常見的超一流:

class A { 
    @JsonView(Object.class) private int id; 
    @JsonView(A.class) private B b; 

    constructors... 
    getters and setters 
} 
0

幾個月後,有很多研究,我實現了自己的解決方案,以保持我的域名清除傑克遜依賴關係。

public class Parent { 
    private Child child; 
    public Child getChild(){return child;} 
    public void setChild(Child child){this.child=child;} 
} 

public class Child { 
    private Parent parent; 
    public Child getParent(){return parent;} 
    public void setParent(Parent parent){this.parent=parent;} 
} 

首先,你必須聲明每個雙向關係的實體中是這樣的:

public interface BidirectionalDefinition { 

    @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id", scope=Parent.class) 
    public interface ParentDef{}; 

    @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id", scope=Child.class) 
    public interface ChildDef{}; 

} 

之後,對象映射器可以自動配置:

ObjectMapper om = new ObjectMapper(); 
Class<?>[] definitions = BidirectionalDefinition.class.getDeclaredClasses(); 
for (Class<?> definition : definitions) { 
    om.addMixInAnnotations(definition.getAnnotation(JsonIdentityInfo.class).scope(), definition); 
}