web-dev-qa-db-fra.com

Comment utiliser @JsonIdentityInfo avec des références circulaires?

J'essaie d'utiliser @JsonIdentityInfo de Jackson 2 comme décrit ici .

À des fins de test, j'ai créé les deux classes suivantes:

public class A
{
    private B b;
    // constructor(s) and getter/setter omitted
}
public class B
{
    private A a;
    // see above
}

Bien sûr, l'approche naïve échoue:

@Test
public void testJacksonJr() throws Exception
{
    A a = new A();
    B b = new B(a);
    a.setB(b);
    String s = JSON.std.asString(a);// throws StackOverflowError
    Assert.assertEquals("{\"@id\":1,\"b\":{\"@id\":2,\"a\":1}}", s);
}

L'ajout de @JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="@id") à la classe A et/ou à la classe B ne fonctionne pas non plus.

J'espérais pouvoir sérialiser (et plus tard désérialiser) a en quelque chose comme ceci:

{
    "b": {
        "@id": 1,
        "a": {
            "@id": 2,
            "b": 1
        }
    }
}

Comment puis je faire ça?

6
Burkhard

Il semble jackson-jr a un sous-ensemble des fonctionnalités de Jackson. @JsonIdentityInfo ne doit pas avoir fait la coupe.

Si vous pouvez utiliser la bibliothèque complète de Jackson, utilisez simplement une variable ObjectMapper avec l'annotation @JsonIdentityInfo que vous avez suggérée dans votre question et sérialisez votre objet. Par exemple

@JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="@id")
public class A {/* all that good stuff */}

@JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class, property="@id")
public class B {/* all that good stuff */}

et alors 

A a = new A();
B b = new B(a);
a.setB(b);
ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.writeValueAsString(a));

va générer

{
    "@id": 1,
    "b": {
        "@id": 2,
        "a": 1
    }
}

où la a imbriquée fait référence à l'objet racine par son @id.

13

Il existe plusieurs approches pour résoudre ces références circulaires ou problèmes de récursion infinie. Ce link explique en détail chacun. J'ai résolu mes problèmes, notamment l'annotation @JsonIdentityInfo au-dessus de chaque entité associée, bien que @JsonView soit plus récent et constitue une meilleure solution selon votre scène.

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")

Ou en utilisant une implémentation IntSequenceGenerator: 

@JsonIdentityInfo(generator=ObjectIdGenerators.IntSequenceGenerator.class)
@Entity
public class A implements Serializable 
...
0
Cassio Seffrin