Как реализовать API для возврата вложенного JSON? - PullRequest
1 голос
/ 06 апреля 2020

Я совершенно новичок в API и недавно разработал свой первый, используя Spring Boot. До сих пор мне удалось получить все записи в базе данных h2 в памяти в виде списка Jsons, но, поскольку я попытаюсь получить их с помощью React и отобразить их в виде древовидного графика с помощью D3, мне также нужно получить их в формате JSON.

Это мой код:

Alien. 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",....}]]

Было бы также хорошо, если бы я мог преобразовать список JSON во вложенный Json, используя React .

Спасибо

Редактировать:

https://i.imgur.com/zuc8D6I.png - Выход почтальона

Ответы [ 2 ]

1 голос
/ 06 апреля 2020

Вам необходимо внести пару изменений, чтобы сделать его иерархическим, пожалуйста, проверьте, как показано ниже:

  1. Добавьте дополнительный столбец 'parent' для поддержания иерархии

    @JsonIgnore
    @ManyToOne(targetEntity = Alien .class, fetch = FetchType.LAZY)
    @JoinColumn(name = "parentId")
    private Alien parent;
    
  2. Как упоминал Гаурав, пожалуйста, измените private String children;, как показано ниже

        @JsonIgnore
        @OneToMany(targetEntity = Alien .class, cascade = CascadeType.ALL, mappedBy = 
        "parent", fetch = FetchType.LAZY)
        private List<Alien> children;
    
  3. Поскольку мы добавили еще один столбец для поддержания иерархии, вам также необходимо внести изменения в вас POST и PUT, при создании ресурса вам нужно передать parent_id

    if(alien.getParentId() == 0) { alien.setParent(null); }else { Alien parent = this.repo.findById(alien.getParentId()); alien.setParent(parent); }

Редактировать: DTO, обычно мы используем для сопоставления данных запроса.

, чтобы работать над кодом, вам необходимо сопоставить объект запроса с объектом dto, который будет иметь имя, другие свойства, parentId, а затем создать объект "Alien" из dto.

a -> New Dto

publi c class 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 одновременно

Parent: только для инопланетной сущности, которая является родительской для другого инопланетянина

parentId: является уникальным идентификатором для родителя

, например: Alien

Здесь мы создали иерархию Alien1 не имеет родителя Alien1 является родителем Alien2 Alien2 является родителем Alien3 и Alien4

0 голосов
/ 06 апреля 2020

Вместо того, чтобы брать детей как строку, берите их как список объектов Замените это:

private String children;

на

List<Alien> children;

и добавьте метод для добавления дочернего элемента

void addChild(Alien child) {
    if(this.children == null) {
        this.children = new ArrayList<>();
    }
    this.children.add(child);
}

Допустим, иерархия равна

A

| _B

| _ C

затем создайте:

Alien c - new Alien();
Alien b = new Alien();
Alien a = new Alien();

b.addChild(c);
a.addChild(b);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...