2013-03-14 14 views
2

У меня двунаправленная связь между двумя объектами. У меня есть веб-служба RESTful, использующая Jersey 1.17 и Jackson 2.1.4. Я также использую аннотацию @JsonIdentityInfo (по-видимому, неправильно), чтобы остановить Json от бесконечного цикла. Однако сгенерированный Json по-прежнему представляет собой бесконечный цикл между двумя объектами.Не удается получить аннотацию @JsonIdentityInfo для работы

первый объект:

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

    private long value; 
    private Parent parent; 

    public long getValue() { 
     return this.value; 
    } 

    public void setValue(long value) { 
     this.value = value; 
    } 

    public Parent getParent() { 
     return this.parent; 
    } 

    public void setParent(Parent parent) { 
     this.parent = parent; 
    } 

} 

второй объект:

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

    private long value; 
    private Set<Child> childs = new HashSet<Child>(0); 

    public long getValue() { 
     return this.value; 
    } 

    public void setValue(long value) { 
     this.value = value; 
    } 

    public Set<Child> getChilds() { 
     return this.childs; 
    } 

    public void setChilds(Set<Child> childs) { 
     this.childs = childs; 
    } 

} 

А вот метод, который генерирует JSON.

@GET 
@Path("/test") 
@Produces(MediaType.APPLICATION_JSON) 
public Child getChild() { 

    Child child = new Child(); 
    Parent parent = new Parent(); 
    child.setValue(1L); 
    parent.setValue(2L); 
    child.setParent(parent); 
    Set<Child> childs = new HashSet<Child>(0); 
    childs.add(child); 
    parent.setChilds(childs); 
    return child; 

} 

EDIT:

В результате Json выглядит следующим образом:

{"value":1,"parent":{"value":2,"childs":[{"value":1,"parent":{"value":2,"childs":[... 

И эти 9 строк были повторены в лог-файл сервера снова и снова ...

at org.codehaus.jackson.map.ser.std.AsArraySerializerBase.serialize(AsArraySerializerBase.java:86) 
at org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:446) 
at org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:150) 
at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:112) 
at org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:446) 
at org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:150) 
at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:112) 
at org.codehaus.jackson.map.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:72) 
at org.codehaus.jackson.map.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:23) 

И файл web.xml выглядит так:

<?xml version="1.0" encoding="UTF-8"?> 
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
    id="WebApp_ID" version="2.5"> 
    <display-name>Jersey REST Service</display-name> 
    <servlet> 
    <servlet-name>Jersey REST Service</servlet-name> 
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class> 
    <init-param> 
     <param-name>com.sun.jersey.config.property.packages</param-name> 
     <param-value>test</param-value>  
    </init-param> 
    <init-param> 
     <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name> 
     <param-value>true</param-value> 
    </init-param> 
    <load-on-startup>1</load-on-startup> 
    </servlet> 
    <servlet-mapping> 
    <servlet-name>Jersey REST Service</servlet-name> 
    <url-pattern>/api/*</url-pattern> 
    </servlet-mapping> 
</web-app> 
+0

Не могли бы вы добавить (части) результирующего JSON, заброшенное исключение (если есть) или что-то вроде этого? – nutlike

+0

@nutlike Я добавил часть результирующего JSON и заброшенное исключение (которое, я считаю, связано с существующим циклом) ... – bbkglb

+0

Я никогда не использовал Джерси, поэтому мое случайное предположение было бы то, что все аннотации Джексона игнорируются в вашем проекте. Не могли бы вы подтвердить (или опровергнуть), что с меньшим примером? Из того, что я читал до сих пор, ваш * web.xml * может быть интересен в этом случае, возможно, вам следует добавить это и на свой вопрос. – nutlike

ответ

3

Для двухсторонней связи между полями вы должны смотреть на @JsonManagedReference и @JsonBackReference аннотаций. Я не думаю, что это поведение может быть достигнуто с помощью @JsonIdentifyInfo вообще.

public class Parent { 

private long value; 
@JsonManagedReference private Set<Child> childs = new HashSet<Child>(0); 

public long getValue() { 
    return this.value; 
} 

public void setValue(long value) { 
    this.value = value; 
} 

public Set<Child> getChilds() { 
    return this.childs; 
} 

public void setChilds(Set<Child> childs) { 
    this.childs = childs; 
} 

} 

...

public class Child { 

private long value; 
@JsonBackReference private Parent parent; 

public long getValue() { 
    return this.value; 
} 

public void setValue(long value) { 
    this.value = value; 
} 

public Parent getParent() { 
    return this.parent; 
} 

public void setParent(Parent parent) { 
    this.parent = parent; 
} 

} 

Вы можете найти больше примеров here.

+5

Это должно быть возможно с помощью аннотации @JsonIdentifyInfo, согласно [this] (http: //wiki.fasterxml.com/JacksonFeatureObjectIdentity), это общее решение с версии 2.0 ... – bbkglb

+0

@ user2102125: Спасибо за ссылку, я этого не знал. – nutlike

+0

hmmm, я не могу заставить его работать с аннотациями JsonManagedReference и JsonBackReference, возможно, что-то не так с конфигурациями моего проекта ... – bbkglb

5

Вы говорите, что используете Jackson 2.1.4, но stacktrace показывает Jackson с пакетами, начиная с «org.codehaus.jackson», который является базовым пакетом для Jackson 1.x. Базовый пакет для Jackson 2.x - «com.fasterxml.jackson». Джерси, таким образом, настроен с Jackson 1.x (скорее всего, 1.9.2, как и the default in Jersey 1.17). Я предполагаю, что вы комментируете свой код с помощью аннотаций, импортированных из Jackson 2.x, но библиотека Джексона, используемая Джерси, не знает о них и поэтому не может сериализоваться.

Ваш код хорошо работает для меня с Jackson 2.3.0.

Смежные вопросы