REST控制器中具有一对多关系的实体的递归JSON视图 [英] Recursive JSON view of an entity with one-to-many relationship in REST controller
问题描述
我正在使用SpringBoot和JPA来构建REST接口。
I'm using SpringBoot and JPA to build a REST interface.
现在,我为从数据库中提取的产品列表返回了一个奇怪的JSON。假设我有:
Now, I have a strange JSON returned for the list of products fetched from the database. Let's say that I have:
@Entity
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@ManyToOne(optional = false, fetch = FetchType.LAZY)
@JoinColumn(name = "categoryId", nullable = false, updatable = false)
private Category category;
...
}
@Entity
public class Category implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@OneToMany(mappedBy = "category", cascade = CascadeType.DETACH)
@OrderBy("name ASC")
private List<Product> products = Collections.emptyList();
...
}
JPA存储库产品
定义为:
The JPA repository for the Product
is defined as:
public interface ProductRepository extends JpaRepository<Product, Long> {
List<Product> findAll();
}
在我的控制器中我有:
@Autowired
private ProductRepository productRepo;
@RequestMapping("/all-products", method = RequestMethod.GET)
public Map<String,Object> home() {
Map<String,Object> model = new HashMap<String,Object>();
model.put("products", productRepo.findAll());
return model;
}
令我疯狂的是,如果我尝试将此服务称为如下:
What is driving my crazy, is that if I try to call this service as follows:
$ curl localhost:8080/all-products
由于表 product
和 category $之间的关系,我得到一个递归输出c $ c>,例如:
{"products":[{"id":1,"name":"Product1","category":
{"id":1,"name":"Cat1","products":[{"id":6,"name":"Product6","category":
{"id":1,"name":"Cat1","products":[{"id":6,"name":"Product6","category":
{"id":1,...
我做错了什么?
推荐答案
你没有做错任何事(至少在代码级别它是相当概念性的) - json serializer就是这样:
You're not doing anything wrong (at least at the code level it's rather conceptual) - json serializer just goes like this:
- 产品 - 序列化它,但等待 - 有一个类别字段,因此序列化程序必须序列化类别字段
- 类别 - 序列化它但是哇它 - 有一个产品领域,因此序列化器必须序列化列表中的每个产品
- 产品 - 因为您的产品系列包含产品&产品包含类别,它进入无限循环,直到超时。
您必须使用视图或跳过它。
You must use a view or just skip it.
-
使用
@JsonView
使用以POJO
查看返回 new ProductView
,其中包含产品的所有字段和新的CategoryView $ c $的引用(类别) c>(你可以在这一点结束)有(产品)
新ProductViewWithoutReferences
的集合,依此类推
Use a view as a POJO
Return new ProductView
that has all fields of product and a reference (category) to new CategoryView
(you can end at this point) that has collection of (products) new ProductViewWithoutReferences
, and so on
对产品系列使用 @JsonIgnore
并且作为旁注 - 如果它是 @RestController
而你正在调用所有产品那么返回其他东西而不是列表有点不寻常。在地图中包装响应是多余的。许多其他客户端在调用 list()
方法时需要一个列表。
And as a side note - if it's a @RestController
and you're invoking "all-products" then it's a bit unusual to return something else than a list. Wrapping the response in a map is redundant. Many rest clients expect a list when they invoke list()
method.
这篇关于REST控制器中具有一对多关系的实体的递归JSON视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!