java - 如何实现 API 以返回嵌套的 JSON?
问题描述
我对 API 完全陌生,最近使用 Spring Boot 开发了我的第一个 API。到目前为止,我已经实现了将 h2 内存数据库中的所有记录作为 Json 列表检索,但是因为我将尝试使用 React 获取它们并使用 D3 在树图中显示它们,所以我还需要获取它们以嵌套的 JSON 格式。
到目前为止,这是我的代码:
外星人.java
package com.example.alien.model;
import java.util.List;
import java.util.Optional;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import com.fasterxml.jackson.annotation.JsonIgnore;
@Entity
public class Alien {
@Id @GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
private String name;
private String type;
private String planet;
@JsonIgnore
@ManyToOne(targetEntity = Alien.class, fetch=FetchType.LAZY)
@JoinColumn(name="parentId")
private Optional<Alien> parent;
@JsonIgnore
@OneToMany(targetEntity = Alien.class, cascade=CascadeType.ALL, mappedBy="parent", fetch=FetchType.LAZY)
private List<Alien> children;
public List<Alien> getChildren() {
return children;
}
public void setChildren(List<Alien> children) {
this.children = children;
}
public Optional<Alien> getParent() {
return parent;
}
public void setParent(Optional<Alien> parent) {
this.parent = parent;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getPlanet() {
return planet;
}
public void setPlanet(String planet) {
this.planet = planet;
}
}
AlienDto.java
package com.example.aliendto;
import java.util.Optional;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import com.example.alien.model.Alien;
import com.fasterxml.jackson.annotation.JsonIgnore;
public class AlienDto {
private String name;
private String type;
private String planet;
private Integer parentId = 0;
public String getName() {
return name;
}
public String getType() {
return type;
}
public String getPlanet() {
return planet;
}
public Integer getParentId() {
return parentId;
}
}
AlienController.java
package com.example.alien.controller;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.example.alien.dao.AlienRepo;
import com.example.alien.model.Alien;
import com.example.aliendto.AlienDto;
@CrossOrigin(origins = "*", allowedHeaders = "*")
@RestController
public class AlienController
{
@Autowired
AlienRepo repo;
@PutMapping("/alien/{id}")
public Alien updateAlien(@RequestBody Alien alien) {
repo.save(alien);
return alien;
}
@DeleteMapping("/alien/{id}")
public String deleteAlien(@PathVariable Integer id)
{
Alien a = repo.getOne(id);
repo.delete(a);
return "deleted";
}
@PostMapping("/alien")
public Alien addAlien(@RequestBody AlienDto dto) {
Alien alien = new Alien();
alien.setName(dto.getName());
alien.setType(dto.getType());
alien.setPlanet(dto.getPlanet());
if(dto.getParentId() == 0) {
alien.setParent(null);
}else {
Optional<Alien> parent = this.repo.findById(dto.getParentId());
alien.setParent(parent);
}
repo.save(alien);
return alien;
}
@GetMapping("/aliens")
public List<Alien> getAliens() {
return repo.findAll();
}
@RequestMapping("/alien/{id}")
public Optional<Alien> oneAlien(@PathVariable("id") Integer id) {
return repo.findById(id);
}
@GetMapping("/")
public String home()
{
return "do_Ob";
}
}
AlienRepo.java
package com.example.alien.dao;
import org.springframework.data.jpa.repository.JpaRepository;
import com.example.alien.model.Alien;
public interface AlienRepo extends JpaRepository<Alien, Integer>
{
}
现在我在 localhost:8080/aliens 上得到这样的结果
[{"id":1,"name":"Javier","type":"Alpha","planet":"Earth","children":"Laia"},
{"id":2,"name":"Javier","type":"Alpha","planet":"Earth","children":"John"},
{"id":3,"name":"Laia","type":"Omega","planet":"Earth","children":""},
{"id":4,"name":"John","type":"Omega","planet":"Earth","children":""}]]
但我也想让他们走另一条这样的路线:
[{"name":"Javier",
"type":"Alpha",
"planet":"Earth",
"children":[{"name": "Laia", "type":"Omega",....},
{"name": "John", "type":"Omega",....}]]
如果我可以使用 React 将 JSON 列表转换为嵌套的 Json 也可以。
谢谢
编辑:
https://i.imgur.com/zuc8D6I.png - 邮递员输出
解决方案
您需要进行一些更改以使其分层,请检查如下:
添加额外的列“父”以维护层次结构
@JsonIgnore @ManyToOne(targetEntity = Alien .class, fetch = FetchType.LAZY) @JoinColumn(name = "parentId") private Alien parent;
正如 Gaurav 所说,请更改
private String children;
如下@JsonIgnore @OneToMany(targetEntity = Alien .class, cascade = CascadeType.ALL, mappedBy = "parent", fetch = FetchType.LAZY) private List<Alien> children;
由于我们添加了一个额外的列来维护层次结构,您还需要在 POST 和 PUT 中进行更改,同时创建您需要传递 parent_id 的资源
if(alien.getParentId() == 0) { alien.setParent(null); }else { Alien parent = this.repo.findById(alien.getParentId()); alien.setParent(parent); }
编辑:DTO,通常我们用来映射请求数据。
要在上面的代码中工作,您需要将 requestbody 映射到 dto 对象,该对象将具有名称、其他属性、parentId,然后从 dto 创建“Alien”对象。
a -> 新的 Dto
公共类 AlientDto {
private String name;
private String type;
private String planet;
private int parentId = 0;
// Getter Setter
}
b-> 控制器更改
@PostMapping("/alien")
public Alien addAlien(@RequestBody AlienDto dto) {
Alien alien = new Alien();
alien.name(dto.getName());
alien.type(dto.getType());
alien.planet(dto.getPlanet());
if(dto.getParentId() == 0) {
alien.setParent(null);
}else {
Alien parent = this.repo.findById(dto.getParentId());
alien.setParent(parent);
}
repo.save(alien);
return alien;
}
或者
更新上面的代码如下
Alien parent = this.repo.findById(<pass parent id here>); // parent id is will be any alien id
alien.setParent(parent);
}
你不能同时拥有 parent 和 parent_id
父母:仅外星实体,它是其他外星人的父母
parentId :是父母的唯一ID
这里我们创建了层次结构 Alien1 没有任何父 Alien1 是 Alien2 的父 Alien2 是 Alien3 和 Alien4 的父
推荐阅读
- python - Octave 的符号包(版本 2.8.0)在 Windows 10 中不起作用
- c# - .NET Core 混合 F# 和 C# 项目 Intellisense 不起作用
- javascript - 这个代码是什么?此代码可以窃取 cookie 吗?
- javascript - Kendo UI 甘特图是否支持计划日期与实际日期比较?
- c# - 在 Blazor 服务器端客户端项目中配置路由
- microsoft-graph-api - 如何通过 Graph API 查询 Azure 安全中心 SecureScore?
- angular - 如何在angular7中同时保持浏览器缩放和锤击js滑动事件
- ssh - 开发人员要求我“向他们发送 SSH 密钥”
- javascript - OVER_QUERY_LIMIT 谷歌地理编码
- amazon-redshift - sqlerrm 变量错误消息存储在 redshift 中的位置