2012-04-17 16 views
24

Utilizo la biblioteca Jackson para la serialización de mis objetos Pojo en la representación JSON. Por ejemplo, tengo clase A y clase B:Jackson JSON serialización, evitación de recursión por definición de nivel

class A { 
    private int id; 
    private B b; 

    constructors... 
    getters and setters 
} 

class B { 
    private int ind; 
    private A a; 

    constructors... 
    getters and setters 
} 

Si desea realizar una serie de objetos de la clase A hay cierta posibilidad de conseguir la recursividad si bien es serializado. Sé que puedo detenerlo usando @JsonIgnore.

¿Es posible limitar la serialización por nivel de profundidad?

Por ejemplo, si el nivel es 2, la serialización se ve de esta manera:

  • serializar un nivel = 0 (0 < 2 OK) -> serializar
  • serializar AB, nivel = 1 (1 < 2 OK) -> serializar
  • aba serializar, nivel = 2 (2 < 2 no es cierto) -> parada

Gracias de antemano.

+0

¿Pudo encontrar finalmente la manera de especificar la profundidad de recursión para la que deseaba que se realizara la serialización? –

+0

Lo resolví usando @JsonIgnore en las entidades referenciadas (con recursividad), así que simplemente no incluí en la serialización. Cuando necesito la instancia específica, ya tengo la ID y hago una llamada adicional para obtener la instancia. No utilicé una solución general, afortunadamente tengo pocos casos. –

Respuesta

12

Comprobar los siguientes enlaces, que podría ayudar:

La única opción después de que sería la creación de su propio módulo personalizado para la serialización/deserialización para su objeto tipo. ver aquí:

Saludos.

4

No hay soporte para ignorar basado en niveles.

Pero puede hacer que Jackson maneje las referencias cíclicas con 2.0, consulte por ejemplo "Jackson 2.0 released" para obtener una explicación sobre cómo usar @JsonIdentityInfo.

20

me encontré recientemente un problema similar: Jackson - serialization of entities with birectional relationships (ciclos evitando)

Así que la solución es actualizar a Jackson 2,0, y añadir a las clases de la siguiente anotación:

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

Esto funciona perfectamente .

+8

esta es una manera muy agradable. pero, ¿conoces una forma de limitar la profundidad del gráfico? – oak

0

En algunos casos, puede limitar la profundidad de serialización utilizando un entero local de subproceso que tenga una profundidad máxima. Vea esto answer.

1

Si desea limitarse a un solo nivel (es decir: si se va a los elementos secundarios del objeto actual y no más), hay una solución simple con @JsonView.

En cada campo que es un enlace a otro objeto, anotar con la clase actual como su punto de vista:

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 
} 

Entonces, cuando la serialización, utilice la clase de objeto como su punto de vista. Serializar una instancia de un haría algo así:

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

Asegúrese de que el DEFAULT_VIEW_INCLUSION se establece en true, o no se representará los campos sin una anotación de @JsonView. Como alternativa, puede anotar todos los demás campos con @JsonView utilizando la clase Object, o cualquier super-clase común:

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

    constructors... 
    getters and setters 
} 
0

Después de varios meses y un montón de investigación, he aplicado mi propia solución para mantener mi dominio libre de las dependencias de 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;} 
} 

En primer lugar, usted tiene que declarar cada una de las entidades de la relación bidireccional en algo como esto:

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

} 

Después de eso, el mapeador objeto puede ser configurado de forma automática:

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