杰克逊-反序列化ManyToOne关系时的惰性列表初始化错误

时间:2018-08-07 09:17:59

标签: java jackson

我有2个简单的课程:

  • Cat
  • CatStore

Cat没有什么特别的,CatStore有一个List<Cat>,该关系映射为:

Cat类中:

@ManyToOne
private CatStore catstore;

CatStore中:

@OneToMany(mappedBy="catstore", fetch=FetchType.EAGER)
private List<Cat> cats;

该关系似乎工作正常,因为当我运行时Jackson可以为我生成正确的JSON

String json = mapper.writeValueAsString(catStore);

但是,如果我尝试反序列化刚生成的JSON,则使用以下行:

CatStore c2 = mapper.readValue(json, CatStore.class);

我听到JsonProcessingException的话

failed to lazily initialize a collection, could not initialize proxy - no Session (through reference chain: fr.truc.java.cleanspringbootMVC.model.CatStore["cats"]

如果CatStore中没有像下面的JSON这样的猫,则反序列化实际上会起作用:

{
  "id":123,
  "cats":["org.hibernate.collection.internal.PersistentBag",[]],
  "name":"NO cats"
}

但这会触发错误:

{
    "id": 121,
    "cats": ["org.hibernate.collection.internal.PersistentBag", [
        ["fr.truc.java.cleanspringbootMVC.model.Cat", {
            "id": 118,
            "name": "luc",
            "nbPattes": 4
        }],
        ["fr.truc.java.cleanspringbootMVC.model.Cat", {
            "id": 119,
            "name": "andré",
            "nbPattes": 4
        }],
        ["fr.truc.java.cleanspringbootMVC.model.Cat", {
            "id": 120,
            "name": "cheval",
            "nbPattes": 4
        }]
    ]],
    "name": "Cat en kit"
}

我真的不知道为什么延迟加载异常会在此处触发,因为数据包含在JSON字符串中。

这与PersistentBag有关吗?

这是因为我没有使用自定义的序列化器/反序列化器吗?

2 个答案:

答案 0 :(得分:1)

如果使用JPA,则将通过字节码增强所有实体,以允许延迟加载等。它们实际上不适合序列化,除非休眠的人知道这一点。但是Jackson对此一无所知,因此它将破坏增强的字节码。

对JPA映射和Jackson映射使用相同的类也不是一个好主意。 JPA类的字段映射到列等,而Jackson的类映射到javascript模式。如果您在同一类中使用它们,则永远不能在不影响JSON模式的情况下更改数据库模式,并且可能破坏与使用JSON的人的向后兼容性。

最好为Jackson使用单独的类(DTO),并在它们之间进行一些映射。或使用mapstruct自动生成一个映射器。

答案 1 :(得分:0)

该错误似乎与mapper.enableDefaultTyping();

有关

启用后,将在JSON中输出每个类的类型。 (我想要的)

由于某种原因,它会导致@ManyToOne出现上述错误

禁用后,PersistentBag不再出现在我的序列化JSON中,并且反序列化有效...