Jackson库进行JSON 序列化时遇到了无限递归(Infinite Recursion)的问题及解决方案

2025-03-19日常编程177557

使用Jackson库进行JSON序列化时遇到了无限递归(Infinite Recursion)问题,这是因为两个实体类ComPointQuotaEntity和 ComPointEntity之间存在双向关联point和pointQuota相互引用,本文给大家介绍解决方案,感兴趣的朋友一起看看吧

目录
  • 解决方案‌
    • 1. 使用 @JsonIgnore 忽略一个方向的引用
    • 2. 使用 @JsonManagedReference 和 @JsonBackReference
    • 3. 使用 DTO 替代直接序列化实体
    • 4. 配置 Jackson 忽略循环引用
    • 5. 自定义序列化器(高级)
  • ‌ 总结‌

    使用 Jackson 库进行 JSON 序列化时遇到了 ‌无限递归(Infinite Recursion)‌ 问题,这是因为两个实体类 ComPointQuotaEntity 和 ComPointEntity 之间存在双向关联(point 和 pointQuota 相互引用),导致序列化时陷入死循环。以下是解决方案:

    解决方案‌

    1. 使用 @JsonIgnore 忽略一个方向的引用

    在其中一个实体类的关联字段上添加 @JsonIgnore 注解,直接阻止某一方的序列化:

    // ComPointQuotaEntity.java
    public class ComPointQuotaEntity {
        @ManyToOne
        @JoinColumn(name = "point_id")
        private ComPointEntity point;  // 保留此字段的序列化
        // 其他字段...
    }
    // ComPointEntity.java
    public class ComPointEntity {
        @OneToMany(mappedBy = "point")
        @JsonIgnore  // 忽略此字段的序列化
        private List<ComPointQuotaEntity> pointQuota;
        // 其他字段...
    }

    2. 使用 @JsonManagedReference 和 @JsonBackReference

    通过注解明确父子关系,Jackson 会序列化父级(@JsonManagedReference),但忽略子级(@JsonBackReference):

    // ComPointQuotaEntity.java
    public class ComPointQuotaEntity {
        @ManyToOne
        @JoinColumn(name = "point_id")
        @JsonManagedReference  // 标记为父级(序列化)
        private ComPointEntity point;
        // 其他字段...
    }
    // ComPointEntity.java
    public class ComPointEntity {
        @OneToMany(mappedBy = "point")
        @JsonBackReference  // 标记为子级(不序列化)
        private List<ComPointQuotaEntity> pointQuota;
        // 其他字段...
    }

    3. 使用 DTO 替代直接序列化实体

    创建 Data Transfer Object (DTO),只暴露需要的字段,避免直接序列化 JPA 实体:

    // ComPointQuotaEntity.java
    public class ComPointQuotaEntity {
        @ManyToOne
        @JoinColumn(name = "point_id")
        @JsonManagedReference  // 标记为父级(序列化)
        private ComPointEntity point;
        // 其他字段...
    }
    // ComPointEntity.java
    public class ComPointEntity {
        @OneToMany(mappedBy = "point")
        @JsonBackReference  // 标记为子级(不序列化)
        private List<ComPointQuotaEntity> pointQuota;
        // 其他字段...
    }

    4. 配置 Jackson 忽略循环引用

    在 application.properties 或 application.yml 中配置 Jackson:

    # application.properties
    spring.jackson.serialization.fail-on-empty-beans=false
    spring.jackson.serialization.fail-on-self-references=false

    或在代码中配置 ObjectMapper:

    @Configuration
    public class JacksonConfig {
        @Bean
        public ObjectMapper objectMapper() {
            return new ObjectMapper()
                .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
                .configure(SerializationFeature.FAIL_ON_SELF_REFERENCES, false);
        }
    }

    5. 自定义序列化器(高级)

    为关联字段自定义序列化逻辑,跳过循环引用:

    public class ComPointQuotaEntity {
        @ManyToOne
        @JoinColumn(name = "point_id")
        @JsonSerialize(using = ComPointEntitySerializer.class)
        private ComPointEntity point;
        // 其他字段...
    }
    public class ComPointEntitySerializer extends JsonSerializer<ComPointEntity> {
        @Override
        public void serialize(ComPointEntity value, JsonGenerator gen, SerializerProvider provider) throws IOException {
            if (value != null) {
                gen.writeStartObject();
                gen.writeNumberField("id", value.getId());
                // 仅序列化需要的字段,跳过 pointQuota
                gen.writeEndObject();
            }
        }
    }

    ‌ 总结‌

    • 推荐方案 2(@JsonManagedReference 和 @JsonBackReference)‌:简单且能保持双向关联。
      ‌>- 推荐方案 3(DTO)‌:彻底解耦序列化逻辑与数据库实体,适合复杂场景。
    • 避免直接序列化 JPA 实体,尤其是涉及双向关联时。

    到此这篇关于Jackson库进行JSON 序列化时遇到了 ‌无限递归(Infinite Recursion)的问题及解决方案的文章就介绍到这了,更多相关Jackson JSON 序列化无限递归内容请搜索北冥有鱼以前的文章或继续浏览下面的相关文章希望大家以后多多支持北冥有鱼!

    您可能感兴趣的文章:

    • Jackson使用示例-Bean、XML、Json之间相互转换
    • 一篇文章了解Jackson注解@JsonFormat及失效解决办法
    • Java中对象 和 json 互转四种方式 json-lib、Gson、FastJson、Jackson
    • 利用Jackson解决Json序列化和反序列化问题
    • Java利用Jackson轻松处理JSON序列化与反序列化
    • Jackson中json格式的字符串与对象的互相转换方式
    • 如何自定义Jackson序列化 @JsonSerialize
    • JSON中fastjson、jackson、gson如何选择
    • jackson 如何将实体转json json字符串转实体
    • 使用jackson实现对象json之间的相互转换(spring boot)
    • 使用Jackson-json解析一个嵌套的json字符串
    本文地址:https://www.ufcn.cn/tutorials/3384268.html

    如非特殊说明,本站内容均来自于网友自主分享,概不代表本站观点,如有任何问题我们都将在收到反馈后的第一时间进行处理!