StackOverflowError序列化递归JSON

我有一个基本的用户类,其中包括一个用户名和一个朋友variables:

data class User ( val username: String, @ManyToMany(fetch = FetchType.EAGER) @JoinTable( name = "users_friends", joinColumns = arrayOf(JoinColumn(name = "user_id", referencedColumnName = "id")), inverseJoinColumns = arrayOf(JoinColumn(name = "friends_id", referencedColumnName = "id"))) val friends: Collection?) 

我从一个springboot控制器调用内置的kotlin函数getFriends():

  @ApiOperation("Get Friends") @RequestMapping(value = "/friends", method = RequestMethod.GET) public Collection getFriends(@RequestParam final String username) { return userService.getFriends(userService.findByUsername(username).get()); } 

其中调用该服务:

 @Override public Collection getFriends(final User user) { Optional myUser = repository.findById(user.getId()); if(myUser.isPresent()){ return myUser.get().getFriends(); } } 

但我得到一个java.lang.StackOverflowError因为UserA有一个UserB的朋友和UserB有一个UserA的朋友,因此当jackson试图序列化用户返回,大概是试图返回像(psudocode):

 userA { friend { userB { friend { userA { etc... etc... } } } } } 

我怎样才能改变控制器,所以它只会返回用户,他们的朋友,然后停止递归?

我已经尝试了@JsonIgnore上的朋友val停止错误,但我不能再检索该值。

我也尝试过@JsonBackReference,但是这是设计,IIRC,OneToMany分辨率。

注意:用户类是Kotlin,其他都是Java

我有这个相同的问题,老实说,我没有find解决方案搜索。 所以我想出了一个序列化的修复(在我的情况下,我用了Gson)。

注意:这个解决方案不完全干净,通常最好的解决方案是在模型结构之间建立更好的关系。 这个解决方案只是为了帮助那些负担不起的人

我的解决方案

循环引用永远是一个常数,即它是在那里或不是。

因此,在序列化之前,通过将循环引用的起点设置为null,然后在序列化之后,我们“再次设置循环”之后,很容易在序列化之前欺骗我们的程序。

基本示例:

 public class Circular { private String name; private Circular friend; public String getName() { return name; } public void setName(String name) { this.name = name; } public Circular getFriend() { return friend; } public void setFriend(Circular friend) { this.friend = friend; } } 

上面的Circular类有一个参考friend 。 它有或没有朋友。 让我们打电话给我们的主要对象A ,它是朋友B AB的朋友,反之亦然( BA的朋友)。 我们的圈子已经创建。 既然我们知道这将永远是一个常数,我们可以这样做:

 //A is an instance of circular A.getFriend().setFriend(null) //Perform serialization 

现在我们可以序列化我们的数据。 然后在反序列化之后,我们简单地设置循环引用:

 //deserialize A A.getFriend().setFriend(A) 

现在我们把原来的对象和循环引用关联起来。

请记住:只有在我早先说过的时候,

你有一个通常的参考或者你没有