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

使用Jackson反序列化含泛型Java类时遇栈溢出,如何解决?

Jackson递归泛型反序列化StackOverflowError问题解决

问题描述

使用Jackson将JSON反序列化为Java对象时,以下类结构在反序列化Menu类时触发StackOverflowError:

public class NavMenu {
    private final List<Menu> menus = new ArrayList<>();
}

public class Menu implements ItemContainer<Menu> {
    private final List<Item<Menu>> items = new ArrayList<>();
}

public class Item<P extends ItemContainer<P>> implements ItemContainer<Item<P>> {
    private final List<Item<Item<P>>> items = new ArrayList<>();
}

public interface ItemContainer<T extends ItemContainer<T>> {
    void add(Item<T> item);
    List<Item<T>> getItems();
}

栈跟踪片段:

java.lang.StackOverflowError
    at com.fasterxml.jackson.databind.type.TypeBase.toCanonical(TypeBase.java:72)
    at com.fasterxml.jackson.databind.type.SimpleType.buildCanonicalName(SimpleType.java:236)
    ...

已通过自定义NavMenu反序列化器解决,但实现递归且难以维护,希望了解是否为Jackson Bug,以及无需自定义反序列化器的解决方法。

问题根源

这不是Jackson的Bug,而是泛型结构导致的无限递归类型解析:

  • Item<P>实现ItemContainer<Item<P>>,同时其items字段定义为List<Item<Item<P>>>
  • 这会让Jackson在解析类型时不断嵌套:Item<Item<Item<...P...>>>,最终耗尽栈空间抛出异常。

无需自定义反序列化器的解决方案

1. 调整泛型结构(推荐)

修改Item类的泛型约束,终止类型的无限嵌套:

public class Item<P extends ItemContainer<P>> implements ItemContainer<P> {
    // 将items类型改为List<Item<P>>,避免嵌套递归
    private final List<Item<P>> items = new ArrayList<>();

    @Override
    public void add(Item<P> item) {
        items.add(item);
    }

    @Override
    public List<Item<P>> getItems() {
        return items;
    }
}

调整后,类型解析会终止在Item<P>,不会产生无限递归。

2. 使用@JsonTypeInfo明确类型边界

若无法修改泛型结构,可通过@JsonTypeInfo注解为Jackson提供类型标识,避免无限解析:

import com.fasterxml.jackson.annotation.JsonTypeInfo;

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
public interface ItemContainer<T extends ItemContainer<T>> {
    void add(Item<T> item);
    List<Item<T>> getItems();
}

该注解会在JSON中添加类全名作为类型标记,让Jackson能准确识别不同层级的递归类型。

3. 用@JsonIgnoreType忽略深层类型(谨慎使用)

如果不需要反序列化深层嵌套的Item实例,可在Item类上添加@JsonIgnoreType,但此方法会忽略所有Item类型的反序列化,仅适用于特定场景:

import com.fasterxml.jackson.annotation.JsonIgnoreType;

@JsonIgnoreType
public class Item<P extends ItemContainer<P>> implements ItemContainer<Item<P>> {
    // ... 原有代码
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 00:00:00