2012-04-17 23 views
24

Uso la libreria Jackson per la serializzazione dei miei oggetti pojo nella rappresentazione JSON. Per esempio io ho di classe A e di classe B:serializzazione Jackson JSON, evasione della ricorsione per definizione del livello

class A { 
    private int id; 
    private B b; 

    constructors... 
    getters and setters 
} 

class B { 
    private int ind; 
    private A a; 

    constructors... 
    getters and setters 
} 

Se voglio serializzare oggetto dalla classe A non v'è certa possibilità di ottenere la ricorsione mentre è serializzato. So che posso fermarlo usando @JsonIgnore.

È possibile limitare la serializzazione a livello di profondità?

Per esempio, se il livello è 2, la serializzazione andrà in questo modo:

  • serializzare un livello = 0 (0 < 2 ok) -> serializzare
  • serialize ab, livello = 1 (1 < 2 ok) -> serializzare
  • serialize aba, livello = 2 (2 < 2 non è vero) -> fermata

Grazie in anticipo.

+0

Sei riuscito a trovare finalmente un modo per specificare la profondità di ricorsione per la quale si desidera che la serializzazione si verifichi? –

+0

Ho risolto usando @JsonIgnore sulle entità di riferimento (con ricorsione), quindi semplicemente non includo nella serializzazione. Quando ho bisogno dell'istanza specifica, ho già l'ID e faccio una chiamata aggiuntiva per ottenere l'istanza. Non ho usato una soluzione generale, per fortuna ho pochi casi. –

risposta

12

Controllare i seguenti link, potrebbe essere utile:

L'unica opzione dopo che potrebbe essere quella di creare il proprio modulo personalizzato per la serializzazione/deserialisation per l'oggetto genere. vedere qui:

saluti.

4

Non c'è supporto per gli ignoranti di livello.

Ma è possibile ottenere Jackson per gestire i riferimenti ciclici con 2.0, vedere ad esempio "Jackson 2.0 released" per la spiegazione su come utilizzare @JsonIdentityInfo.

20

Recentemente ho incontrato un problema simile: Jackson - serialization of entities with birectional relationships (cicli evitando)

Quindi la soluzione è quella di effettuare l'aggiornamento a Jackson 2.0, e aggiungere alle classi la seguente annotazione:

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

Questo funziona perfettamente .

+8

questo è davvero un bel modo. ma conosci un modo per limitare la profondità del grafico? – oak

0

In alcuni casi è possibile limitare la profondità di serializzazione utilizzando un intero locale thread che mantiene la profondità massima. Vedi questo answer.

1

Se si vuole limitare a un solo livello (es: si va ai figli dell'oggetto corrente e non oltre), v'è un soluzione semplice con @JsonView.

Su ogni campo che è un collegamento a un altro oggetto, annotare con la classe corrente come visualizzazione:

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 
} 

Poi, durante la serializzazione, utilizzare la classe di oggetti come il vostro punto di vista. Serializzazione di un istanza di un renderebbe qualcosa di simile:

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

Assicurarsi che il DEFAULT_VIEW_INCLUSION è impostata su true, oppure i campi senza un'annotazione @JsonView non sarà reso. In alternativa, è possibile annotare tutti gli altri campi con @JsonView utilizzando la classe Object, o qualsiasi comune super-classe:

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

    constructors... 
    getters and setters 
} 
0

Dopo diversi mesi e un sacco di ricerca, ho implementato la mia soluzione per mantenere il mio dominio chiaro delle dipendenze di Jackson.

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

In primo luogo, si deve dichiarare ciascuno dei vostri entità del rapporto bidirezionale in qualcosa di simile:

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{}; 

} 

Dopo di che, il mapper oggetto può essere configurato automaticamente:

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