2017-08-16 118 views
6

我嘗試了幾次搜索時發現的事情,但沒有任何幫助,或者我沒有正確實現它。導致循環超類問題的直接自引用JSON

錯誤我得到

Direct self-reference leading to cycle (through reference chain: io.test.entity.bone.Special["appInstance"]->io.test.entity.platform.ApplicationInstance["appInstance"]) 

這兩個擴展基礎機構,並在基地(超類),它有一個appInstance爲好。

基礎機構類似於這樣

@MappedSuperclass 
public abstract class BaseEntity implements Comparable, Serializable { 

@ManyToOne 
protected ApplicationInstance appInstance; 

//getter & setter 

} 

應用實體看起來像這樣

public class ApplicationInstance extends BaseEntity implements Serializable { 
    private List<User> users; 
// some other properties (would all have the same base and application instance . User entity will look similar to the Special.) 
} 

特殊實體

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "objectType") 
@JsonIgnoreProperties({"createdBy", "appInstance", "lastUpdatedBy"}) 
public class Special extends BaseEntity implements Serializable { 

    @NotNull 
    @Column(nullable = false) 
    private String name; 

    @Column(length = Short.MAX_VALUE) 
    private String description; 

    @NotNull 
    @Column(nullable = false) 
    private Double price; 

    @OneToOne 
    private Attachment image; 

    @Enumerated(EnumType.STRING) 
    @ElementCollection(targetClass = SpecialTag.class) 
    @CollectionTable(name = "special_tags") 
    @Column(name = "specialtag") 
    private List<SpecialTag> specialTags; 

    @Temporal(TemporalType.TIME) 
    private Date specialStartTime; 

    @Temporal(TemporalType.TIME) 
    private Date specialEndTime; 

    @Enumerated(EnumType.STRING) 
    @ElementCollection(targetClass = WeekDay.class) 
    @CollectionTable(name = "available_week_days") 
    @Column(name = "weekday") 
    private List<WeekDay> availableWeekDays; 

    @OneToMany(mappedBy = "special", cascade = CascadeType.REFRESH) 
    private List<SpecialStatus> statuses; 

    @OneToMany(mappedBy = "special", cascade = CascadeType.REFRESH) 
    private List<SpecialReview> specialReviews; 

    @Transient 
    private Integer viewed; 

    private Boolean launched; 

    @OneToMany(mappedBy = "special") 
    private List<CampaignSpecial> specialCampaigns; 


    @Override 
    @JsonIgnore 
    public ApplicationInstance getAppInstance() { 
    return super.getAppInstance(); 
    } 
} 

特殊的所有實體從BaseEntity繼承包含AppInstance

然後我有一個方法來獲得特殊

@GET 
@Path("{ref}") 
@Produces(MediaType.APPLICATION_JSON) 
@Consumes(value = MediaType.TEXT_PLAIN) 
public Special findByGuestRef(@PathParam("ref") String pRefeference) { 
    // find the special and return it 
return special; 
} 

在我嘗試以下

  • 新增jsonIgnoreProperties
  • 增加了一個覆蓋了appInstance與@JsonIgnore
  • 註釋的特殊實體@JsonIdentityInfo

abov的鏈接Ë

沒有這些解決方案的工作。難道我做錯了什麼?

注意:是否也可以編輯特殊的,因爲其他實體位於不同的包中,並且不想編輯它們。

+0

使'protected ApplicationInstance appInstance'專用併爲其添加一些getter(s)和setter(s)(protected或public),然後使用'@ JsonIgnore'註釋覆蓋'ApplicationInstance'中的getter(s)。 – ConductedClever

+0

@aristotll我已經添加了一些細節,但不認爲它會改變。所有引用應用程序實例 –

+0

只是爲了澄清:你只會從這個實例中排除appInstance,這就是爲什麼你不能在映射類中添加'@ JsonIgnore'? – Mark

回答

2

通常排除響應中的屬性與向其getter添加註釋@JsonIgnore一樣簡單,但是如果不想將此註釋添加到父類,則可以重寫getter,然後在其上添加註釋:

public class Special extends BaseEntity implements Serializable { 
    ... 
    @JsonIgnore 
    public ApplicationInstance getAppInstance() { 
     return this.appInstance; 
    } 
    ... 
} 

注意:由於有幾個框架,確保您使用的是正確@JsonIgnore註解,否則將被忽略,看看this answer例如。

另一種選擇,更多的「手冊」,只是創建響應一個bean這將是特殊情況下的一個子集:

@GET 
@Path("{ref}") 
@Produces(MediaType.APPLICATION_JSON) 
@Consumes(value = MediaType.TEXT_PLAIN) 
public SpecialDTO findByGuestRef(@PathParam("ref") String pRefeference) { 
    // find the special and return it 
return new SpecialDTO(special); 
} 


public class SpecialDTO { 

    //declare here only the attributes that you want in your response 

    public SpecialDTO(Special sp) { 
     this.attr=sp.attr; // populate the needed attributes 
    } 

} 
+0

謝謝,手冊確實可以使用並可以使用它。將嘗試另一種方式來編輯超類,因爲我有很多像特殊的實體,不想爲每個類創建一個DTO類。 –

+0

請告訴我們,如果它的工作,因爲我沒有測試它,這只是一個理論的解決方案 –

+0

我已經嘗試過,仍然無法正常工作。現在我將使用建議的「手動選項」,目前可行。 –

0

對我來說,問題似乎是在特殊對象和字段正在被初始化。 我想在序列化發生時檢測到循環引用。 類似的東西來:

class A { 
    public A child; 
    public A parent; 
} 

A object = new A(); 
A root = new A(); 
root.child = object; 
object.parent = root; 

在上面的代碼,只要你會嘗試seralize這兩種對象,你將面臨同樣的問題。 請注意,不建議使用公共字段。

我會建議您查看您的特殊對象和其中的參考。

+1

請閱讀整個問題,OP知道它。問題是如何在不修改聲明有問題屬性的父類的情況下解決這個問題 –