본문 바로가기
SpringBoot Server/API

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

by ssury94 2024. 12. 18.

 

서버 작업할때는 
먼저 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", "해당 책은 없습니다.");
    }

}