SpringBoot Server/API

JSON의 이해, 책 정보 CRUD 만들기 예제

ssury94 2024. 12. 18. 17:35

 

서버 작업할때는 
먼저 Postman에서 서버 리퀘스트 API를 먼저 생성해두고 작업합시다.

어떻게 처리하면 (Request) 원하는 결과가 나오는지 (Response) 바로 확인이 가능하니까!

 

 

 

API 명세서를 확인해서

요청사항을 파악한 후 Postman에서 이 API가 어떻게 작동해야할지 계획하고나서 코드를 작성한다.

 

책을 저장하는 API를 만든다고 생각해보자.

클라이언트가 책 정보들을 입력하면 서버가 저장을 하는 식으로 진행되겠지?

그런데 어떻게 입력하지?


JSON이란?

JSON(JavaScript Object Notation)은 데이터를 구조화하여 저장하거나 전송할 때 사용되는 경량 데이터 형식입니다. 간단하고 사람이 읽기 쉬운 텍스트 형식으로 데이터를 표현할 수 있으며, 특히 웹 애플리케이션에서 서버와 클라이언트 간 데이터를 주고받는 데 널리 사용됩니다.

json

{

  "id": "string",

  "title": "string",

  "author": "string"

}

 

객체 (Object)  중괄호 {} 로 감싸인 키 - 값 쌍(pair)으로 구성

 

{
  "과일": ["사과", "바나나", "체리"]
}

배열 (Array): 대괄호 [] 로 감싸인 키 - 값의 목록(List)으로 구성

 

자바에서의 arrayList, HashMap 과 닮았다.

Json데이터는 항상 키(String)값(String, Number, Boolean, Objcet, Array, null)으로 구성된다. 

 

{
  "recipes": [
    {
      "id": 1,
      "name": "Egg Salad",
      "description": "Place an egg in a saucepan and cover it with water. Bring to a boil, then reduce heat and simmer for 10-12 minutes. Cool the eggs, peel them, and mix with mayonnaise, mustard, salt, and pepper."
    },
    {
      "id": 2,
      "name": "Tomato Pasta",
      "description": "Bring a large pot of lightly salted water to a boil. Add pasta and cook until al dente. In a separate pan, sauté garlic in olive oil, add chopped tomatoes, and simmer. Combine with pasta and serve."
    }
  ]
}

 

키: recipes
객체: 각 레시피 객체는 id, name, description 속성을 가지고 있다
형식: JSON 형식은 중괄호 {}로 객체를 정의하고 대괄호 []로 배열을 정의


 

* JSON방식으로 리퀘스트를 하는것은 (=데이터를 보내는것은)  put, post만 쓴다!

 

이렇게 HTTP 프로토콜을 통해 자원(Resource)의 상태를 주고받는 방식을 restful API 이라고 한다!

 

 


 

 

json

{

  "id": "string",

  "title": "string",

  "author": "string"

}

랑 매칭되게 entitiy 클래스 변수를 선언한다.

 

package com.marurun66.book.entity;
import lombok.*;

//// getter setter 한번에 처리해주는 어노텐션 @Data - lombok 제공
//@Data
//// 기본 생성자 만들어주는 어노텐션 @NoArgsConstructor
//@NoArgsConstructor
//// 모든 파라미터 처리해주는 생성자 어노텐션 @AllArgsConstructor
//@AllArgsConstructor

public class Book {
    private String id;
    private String title;
    private String author;

    public Book() {
    }

    public Book(String id, String title, String author) {
        this.id = id;
        this.title = title;
        this.author = author;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }
}

 

lombok이 생성자, getter setter 모두 깔끔하게 지정이가능하다해서 기대가 컸는데

무슨 오류인지 적용이 안됨.

선생님께서 설정방법을 알려주셨다!


 

package com.marurun66.book.cotroller;

import com.marurun66.book.entity.Book;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Map;
import java.util.Objects;

@RestController
public class BookController {
    // 책을 저장하고, 가져오는 프로젝트

    // API 명세서 확인 - 서로 주고받는 데이터
    // 클라이언트에서 리퀘스트하면 서버에서는 이렇게 리스폰하라는 지침

    // 기본 url http://localhost:8080/api/books


    // Book ArrayList는 controller 담당이니 컨트롤러클래스에 생성자
    ArrayList<Book> bookList = new ArrayList<>();

    //CRUD

    //2) 책 생성 (POST) R
    @PostMapping("/api/books")
    public Map<String, Object> createBook(@RequestBody Book book) {
        // 클라이언트가 보내주는 데이터는 Book book에 저장
        // 클라이언트는 joson으로 보내준다 = 묶음처리로 보내준다
        // 그럼 고대로 받을 수 있는 클래스를 만들어준다 - Book클래스
        // 근데 private네? Book클래스에서 getter setter를 롬복 @ 으로 설정해보자

        //createBook 메서드에서 public Map<String, Object> createBook(@RequestBody Book book)는
        // Book 객체를 받아서 처리한 후, 결과를 Map<String, Object> 형태로 반환하는 구조입니다.

        bookList.add(book);
        //클라이언트가 보낸 {
        //  "id": "B01",
        //  "title": "재밌는책",
        //  "author": "홍길동"
        //}joson을 book에 저장하라

        //응답
        return Map.of("message", "created successfully", "book", book);
        // key value
        // book = id, title, author
        // {} 에 들어간 데이터는 순서상관없이 출력된다 HashMap
    }

    //1) 책 조회 get C
    @GetMapping("/api/books/{id}")
    public Map<String, Object> getBook(@PathVariable String id) {
        for (Book book : bookList) {
            if (book.getId().equals(id)) {
                return Map.of("book", book);
            }
        }
        return Map.of("book", "해당 책이 없습니다.");
    }


    //3) 책 수정 put U
    @PutMapping("/api/books/{id}") //id는 변수여서 {}
    public Map<String, Object> updateBook(@PathVariable String id, @RequestBody Book book) {
        //유저가 보내는 데이터가 파라미터로 들어가게 세팅
        // 기존 책을 업데이트하는거니 기존책 먼저 찾기
        for (Book savedBook : bookList) {
            if (savedBook.getId().equals(id)) {
                savedBook.setTitle(book.getTitle());
                savedBook.setAuthor(book.getAuthor());
                return Map.of("message", "Book updated successfully",
                        "book", savedBook);
            }
        }
            return Map.of("message", "해당 책은 없습니다.");
        }

    //4) 책 삭제 delete D
    @DeleteMapping("/api/books/{id}")
    public Map<String, Object>deleteBook(@PathVariable String id) {
        for (Book book : bookList) {
            if (book.getId().equals(id)) {
                bookList.remove(book);
                return Map.of("message", "Book deleted successfully");

            }
        }
        return Map.of("message", "해당 책은 없습니다.");
    }

}