两个对象之间的父子关系导致JSON StackOverflowError [英] Parent-child relation between two objects causes JSON StackOverflowError

查看:627
本文介绍了两个对象之间的父子关系导致JSON StackOverflowError的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图在某些对象之间建立父子关系,但遇到了一些麻烦.

I am trying to achieve a parent-child relation between some objects and I ran into a bit of trouble.

就我而言,我试图将对象存储在其他对象内(例如,容器存储多个项目或其他包含项目的容器).棘手的是,存储中的每个对象都应该能够分辨出其最外层的父对象是什么.尽管这似乎在我的内存数据库中有效(目前使用h2),但是尝试获取所有存储项的JSON表示可以做到这一点(我返回List<StorageUnit>):

In my case, I am trying to store objects within other objects (e.g. container stores multiple items or other containers with items). The tricky part is that every object in the storage should be able to tell what it's outermost parent object is. While this seems to work in my in-memory database (using h2 at the moment), trying to get a JSON representation of all my storage items gives this (I return a List<StorageUnit> ):

无法编写JSON:无限递归(StackOverflowError);嵌套异常是com.fasterxml.jackson.databind.JsonMappingException:无限递归(StackOverflowError)(通过参考链:java.util.ArrayList [0]-> com.warehousing.storage.FixedContentsCase ["contents"]-> java.util .ArrayList [0]-> com.warehousing.storage.FixedContentsCase ["contents"]-> ...

Could not write JSON: Infinite recursion (StackOverflowError); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: java.util.ArrayList[0]->com.warehousing.storage.FixedContentsCase["contents"]->java.util.ArrayList[0]->com.warehousing.storage.FixedContentsCase["contents"]->...

以下是课程:

StorageUnit

@Entity
@Inheritance
public abstract class StorageUnit {

   @Id
   @GeneratedValue(strategy=GenerationType.IDENTITY)
   private Long id;
   @ManyToOne
   private Location location;
   protected Long parentContainerId;
   // <getters & setters> 
   public abstract List<StorageUnit> getContents();
}

FixedContentCase


@Entity
public class FixedContentsCase extends StorageUnit {
    @OneToMany
    private List<Item> items; 

    public FixedContentsCase() {
        super();
        items = new ArrayList<>();
    }
    // <getters & setters> 
    @Override
    public List<StorageUnit> getContents() {
        // Return the case itself and its contents
        List<StorageUnit> contents = new ArrayList<>(Arrays.asList(this));
        for (StorageUnit item : items) 
            contents.addAll(item.getContents());
        return contents;
    }   
}

项目

@Entity
public class Item extends StorageUnit {

    private String description;

    public Item() {
        super();
        this.description = "";
    }
    // <getters & setters> 
    @Override
    public List<StorageUnit> getContents() {
        return Arrays.asList(this);
    }   
}

我试图用@JsonIgnoreProperties("parentContainerId")注释StorageUnit类,但是没有用.用@JsonIgnore注释parentContainerId也没有帮助.我还尝试注释获取器而不是属性本身(按照以下).有没有办法解决此问题,或者是否需要某种设计更改?谢谢!

I have tried to annotate the StorageUnit class with @JsonIgnoreProperties("parentContainerId") but it didn't work. Annotating parentContainerId with @JsonIgnore didn't help either. I also tried annotating the getters instead of the attributes themselves (as per following). Is there a way to work around this or is some kind of design change necessary? Thanks!

推荐答案

您的问题是,将存储单元本身添加到其内容列表中,如果向下遍历树,则会导致无限递归.解决方案:使用引用,并仅使用@JsonIdentityInfo@JsonIdentityReference将对象序列化一次:

Your problem is that you add the storage unit itself to its list of contents, leading to infinite recursion if you traverse the tree downwards. The solution: Use a reference and only serialize the object once, using @JsonIdentityInfo and @JsonIdentityReference:

public class MyTest {

    @Test
    public void myTest() throws JsonProcessingException {
        final FixedContentsCase fcc = new FixedContentsCase();
        fcc.setId(Long.valueOf(1));
        final Item item = new Item();
        item.setId(Long.valueOf(2));
        item.setDescription("item 1");
        fcc.getItems().add(item);
        final ObjectMapper om = new ObjectMapper();
        System.out.println(om.writeValueAsString(fcc));
    }
}

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
@JsonIdentityReference(alwaysAsId = false)
class Item extends StorageUnit {

    ...
}

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
@JsonIdentityReference(alwaysAsId = false)
class FixedContentsCase extends StorageUnit {

    ...
}

abstract class StorageUnit {

    ...
}

这篇关于两个对象之间的父子关系导致JSON StackOverflowError的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆