You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何@JsonIgnore能修复同一实体父子关系的JSON无限递归问题?

解决父子实体JSON序列化时的无限递归问题

最近在给Trash实体类做父子关联的时候踩了个坑:当我发起GET请求获取带有子实体的对象时,直接触发了栈溢出错误,看报错信息是无限递归导致的。后来在parent字段上加了@JsonIgnore注解就搞定了,这里给大家拆解下问题根源和这个注解的修复原理。

问题重现的代码和报错

实体类代码

@Entity @Table(name = "trash")
public class Trash {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @NotBlank
    private String username;
    @NotBlank
    private String message;
    private Long likes;
    @ManyToOne(cascade = CascadeType.ALL,fetch = FetchType.LAZY)
    @JsonIgnore // 加了这个注解解决问题
    private Trash parent;
    @OneToMany(cascade = CascadeType.ALL, mappedBy="parent", orphanRemoval=true, fetch = FetchType.LAZY)
    private Collection<Trash> children;
}

报错信息

2019-07-19 10:29:55.867 ERROR 14156 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Infinite recursion (StackOverflowError); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: com.example.litter.model.Trash["parent"]->com.example.litter.model.Trash$HibernateProxy$lBPNIlf1["children"]->org.hibernate.collection.internal.PersistentBag[0]->com.example.litter.model.Trash["parent"]->...重复多次...->com.example.litter.model.Trash["parent"])] with root cause java.lang.StackOverflowError: null

原问题的根源

这个问题的核心是双向关联导致的JSON序列化无限递归:

  • 我们的Trash实体是双向关联:父对象通过children字段关联子对象,子对象通过parent字段关联父对象;
  • 当Spring MVC要把Trash对象转换成JSON返回给前端时,会用Jackson遍历对象的所有字段进行序列化:
    1. 先序列化一个父Trash对象,处理到children字段时,会逐个序列化每个子Trash对象;
    2. 序列化子Trash对象时,又会处理它的parent字段,回到父Trash对象;
    3. 父对象再次被序列化时,又会处理children字段,再次进入子对象的序列化,循环往复没有终止;
  • 这个递归过程会持续消耗栈内存,直到栈空间耗尽,就抛出了StackOverflowError,报错信息里的引用链也清晰展示了这个循环路径。

@JsonIgnore注解的修复原理

@JsonIgnore是Jackson JSON库提供的核心注解,它的作用很直接:告诉JSON序列化器和反序列化器,完全忽略被标注的字段。

  • 当我们给parent字段加上这个注解后,Jackson在序列化Trash对象时,会跳过parent字段的处理:
    1. 序列化父对象时,正常处理children集合,生成子对象的JSON;
    2. 序列化子对象时,不会去处理它的parent字段,也就不会回到父对象触发循环;
  • 这就彻底打断了递归链,序列化过程可以正常完成,自然不会再出现栈溢出的问题。

小补充:如果需要在JSON中保留parent的部分信息,也可以用@JsonManagedReference(标记父方的children字段)和@JsonBackReference(标记子方的parent字段)组合,它们会处理双向关联的序列化,避免递归,同时保留关联信息。不过如果不需要返回parent字段,@JsonIgnore是最简单高效的方案。

内容的提问来源于stack exchange,提问作者Eric Tercasio

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:17:06