Java 生成 JSON 栈溢出错误 (StackOverflowError) 解决方案

半杯拿铁
半杯拿铁
发布时间:2026-10-15 | 2人浏览过
原创

在使用 Java(特别是结合 Hibernate)将实体对象序列化为 JSON 时,若实体间存在一对多或多对一的关联关系且未做特殊处理,极易产生 java.lang.StackOverflowError 栈溢出错误。这是因为 JSON 库在尝试序列化关联对象时会陷入无限递归。

问题复现:为什么会出现栈溢出?

通常我们在 Service 层查询数据并直接转换为 JSON 返回给前端时,代码如下:

List<Comment> commentsList = commentMng.findByArticleId(articleid);
JSONArray jsonMembers = new JSONArray(commentsList);

如果 Comment 实体中的字段都是普通属性,上述操作没有问题。但如果 Comment 表通过外键与 Article 表建立了多对一(Many-to-One)的关系,即一个 Article 包含多个 Comment:

  • Comment 对象中包含一个 Article 类型的成员变量。
  • Article 对象中可能包含一个 List<Comment> 类型的一级集合。

此时直接使用工具类(如 Jackson、Fastjson 等)自动遍历序列化,程序会沿着“评论→文章→评论列表”的路径无限递归,最终导致 栈内存溢出(StackOverflowError)。

解决方案一:忽略关联字段(推荐)

最简单的做法是在代码层面告诉 JSON 序列化器:“忽略这个会导致循环引用的字段”。根据你项目中使用的 JSON 库不同,注解有所区别:

  1. Jackson 库:使用 @JsonIgnore 注解。
  2. Fastjson 库:使用 @JSONField(serialize = false) 注解。

建议直接在实体类的 Getter 方法或成员变量上加注。当不确定具体使用的是哪个底层库时,可以同时添加两个注解以防遗漏。例如:

// Fastjson 示例
@JSONField(serialize = false)
private Article article;

// Jackson 示例  
@JsonIgnore
private List<Comment> commentsList;

解决方案二:手动扁平化数据结构

如果你不仅需要忽略关联字段,还需要将关联信息(如文章标题)提取出来传入前台,则不能简单地将整个 Comment 对象丢进列表。需要手动实例化 JSONObject,将需要的值单独取出放入 Map 或 JsonObject 中。

JSONArray jsonMembers = new JSONArray();
for (Comment comment : commentsList) {
    JSONObject jsonObject = new JSONObject();
    // 提取基础字段
    jsonObject.put("id", comment.getId());
    jsonObject.put("content", comment.getContent());
    
    // 提取关联对象信息(转为字符串),避免嵌套对象导致的序列化死循环
    if (comment.getArticle() != null) {
        jsonObject.put("articleTitle", comment.getArticle().getTitle());
    }
    
    jsonMembers.put(jsonObject);
}

这种方法完全切断了序列化器的自动导航机制,确保传输的是扁平的、安全的纯文本或基础数据类型。

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表