使用@JsonIdentityInfo时对null ID进行无限递归

时间:2020-09-07 20:33:30

标签: java json spring jackson

我有2个DTO双向结构CategoryProduct,其中Productone-to-many关系中的多面。我想通过REST将它们作为JSON传输到前端层。当已经分配了ID(用于更新操作)时,我没有任何问题,但是当ID为空(创建)时,我面临着众所周知的无限递归。

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property="categoryId")
public class CategoryDTO implements Serializable {
    private Long categoryId;
    private String categoryName;
    private List<ProductDTO> products = new LinkedList<>();

    public void addProduct(ProductDTO product) {
        products.add(product);
        product.setCategory(this);
    }

    // remove synchronization method, setters, getters
}
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property="productId")
public class ProductDTO implements Serializable {
    private Long productId;
    private String productName;
    private CategoryDTO category;

    // setters, getters
}

但是,当我使用@JsonManagedReference@JsonBackReference时,一切都很好。我收到漂亮的json:

{
   "categoryId":null,
   "categoryName":"category_name",
   "products": [
      {
         "productId":null,
         "productName":"product1"
      }
   ]
}
public class CategoryDTO implements Serializable {
    private Long categoryId;
    private String categoryName;

    @JsonManagedReference
    private List<ProductDTO> products = new LinkedList<>();

    public void addProduct(ProductDTO product) {
        products.add(product);
        product.setCategory(this);
    }

    // remove synchronization method, setters, getters
}
public class ProductDTO implements Serializable {
    private Long productId;
    private String productName;

    @JsonBackReference
    private CategoryDTO category;

    // setters, getters
}

在两个示例中,其余方面都在下面:

@RestController
public class CategoryController {
    @GetMapping(path = "/categories")
    public ResponseEntity<CategoryDTO> fetchCategories() {
        CategoryDTO category = new CategoryDTO();
        category.setCategoryName("category_name");

        ProductDTO product1 = new ProductDTO();
        product1.setProductName("product1");

        category.addProduct(product1);

        return new ResponseEntity<>(category, HttpStatus.OK);
    }
}

为什么@JsonManagedReference@JsonBackReference有效,而@JsonIdentityInfo无效?

感谢阅读。

1 个答案:

答案 0 :(得分:0)

@JsonManagedReference@JsonBackReference使用对象实例引用,因此,当您将Product添加到Category时,而@JsonIdentityInfo使用来自值的ID时,它可以工作领域。

答案在WritableObjectIdBeanSerializerBase#_serializeWithObjectId(Object, JsonGenerator, SerializerProvider, boolean)类别中。

换句话说,对于非空字段,序列化器记得他序列化了给定的类实例,但是他不能对空字段进行序列化。当您按下端点/categories时,您会看到。在连接中断之前,会生成无限的JSON。

如果我错了,请有人纠正我。

注意: Imo,您只需删除字段private CategoryDTO category或将其更改为private Long categoryId,您将摆脱任何注释:D同样,您也不会遇到任何问题无限递归。