JSON의 개념 및 "사용법"

투민·2023년 9월 2일

JSON

#JavaScript Object Notation(자바스크립트 객체 표기법)

JSONSimple - JSON Value

JSONValue 클래스는 JSON 데이터를 파싱하고 인코딩하는 데 사용되는 유틸리티 클래스

  1. 파싱(Parsing):
    • parse(Reader in)parse(String s) 메서드를 사용하여 텍스트를 Java 객체로 파싱
    • parse 메서드는 JSON 텍스트를 읽어와 JSON 객체 또는 배열, 문자열, 숫자, 불리언, 또는 null로 변환
  2. 인코딩(Encoding):
    • writeJSONString(Object value, Writer out) 메서드를 사용하여 Java 객체를 JSON 텍스트로 인코딩할 수 있음.
    • toJSONString(Object value) 메서드를 사용하여 Java 객체를 JSON 문자열로 변환 가능.
  3. JSONAware 및 JSONStreamAware 지원:
    • JSONAwareJSONStreamAware 인터페이스를 구현한 객체에 대한 처리를 지원.
    • JSONAware는 객체를 JSON 문자열로 표현하는 데 사용되고, JSONStreamAware는 객체를 JSON 데이터를 스트림으로 출력하는 데 사용
    • "스트림으로 처리한다"는 말은 데이터를 한 번에 모두 메모리에 로드하지 않고 데이터를 조각조각 읽거나 쓰는 것을 의미
//JSON Value 예제
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;

public class JSONParseExample {
    public static void main(String[] args) {
        // JSON 문자열 생성
				// 공백은 \로 처리 CSV는':'로 구분
        String jsonString = "{\"name\":\"John\",\"age\":30,\"isStudent\":false,\"hobbies\":[\"Reading\",\"Gaming\",\"Cooking\"],\"address\":{\"street\":\"123 Main St\",\"city\":\"New York\",\"zipCode\":\"10001\"}}";

        // JSON 문자열 파싱
        Object parsedObject = JSONValue.parse(jsonString);

        // 파싱된 객체를 JSONObject로 캐스팅
        JSONObject jsonObject = (JSONObject) parsedObject;

        // JSON 객체에서 값을 추출
				// jsonObject의 get 메소드를 사용하여 value값 추출
        String name = (String) jsonObject.get("name");
        Long age = (Long) jsonObject.get("age");
        Boolean isStudent = (Boolean) jsonObject.get("isStudent");
        JSONObject address = (JSONObject) jsonObject.get("address");

        // JSON 배열 추출
        JSONArray hobbies = (JSONArray) jsonObject.get("hobbies");

        // 출력
        System.out.println("Name: " + name);
        System.out.println("Age: " + age);
        System.out.println("Is Student: " + isStudent);
        System.out.println("Address: " + address.toJSONString());

        System.out.print("Hobbies: ");
        for (Object hobby : hobbies) {
            System.out.print(hobby + ", ");
        }
    }
}

JSONSimple -JSON Object

JSONObject 클래스는 JSON 객체를 표현하고 다루기 위한 클래스

이 클래스는 java.util.Map 인터페이스를 구현하며, JSON 객체의 키-값 쌍을 관리

  • public class JSONObject extends HashMap implements Map, JSONAware, JSONStreamAware
    • HashMap을 확장한 JSON 객체
    • Map, JSONAware, JSONStreamAware 인터페이스를 구현하여 다양한 사용 사례를 지원
  • public static void writeJSONString(Map map, Writer out) throws IOException
    • 주어진 map을 JSON 문자열로 인코딩하고 Writer를 통해 출력합
    • JSONAware 및 JSONStreamAware 지원 객체에 대한 특별한 처리를 수행
  • public void writeJSONString(Writer out) throws IOException
    • 현재 JSON 객체를 JSON 문자열로 인코딩하고 Writer를 통해 출력
  • public static String toJSONString(Map map)
    • 주어진 map을 JSON 문자열로 변환
    • JSONAware 객체의 특별한 처리를 수행하지 않으며, 단순히 JSON 형식의 문자열을 반환
  • public String toJSONString()
    • 현재 JSON 객체를 JSON 문자열로 변환
  • private static String toJSONString(String key, Object value, StringBuffer sb)
    • 특정 키와 값을 사용하여 JSON 문자열을 구성
  • public static String toString(String key, Object value)
    • 특정 키와 값을 사용하여 JSON 문자열을 생성

Json-simple을 통한 예제

//JSON Object 예제
import org.json.simple.JSONObject;
import org.json.simple.JSONArray;

public class JSONSimpleExample {
    public static void main(String[] args) {
        // JSON 객체 생성
        JSONObject jsonObject = new JSONObject();

        // JSON 객체에 값을 추가
        jsonObject.put("name", "John");
        jsonObject.put("age", 30);
        jsonObject.put("isStudent", false);

        // JSON 배열 생성 및 값 추가
        JSONArray hobbies = new JSONArray();
        hobbies.add("Reading");
        hobbies.add("Gaming");
        hobbies.add("Cooking");
        jsonObject.put("hobbies", hobbies);

        // 내부 JSON 객체 생성 및 값 추가
        JSONObject address = new JSONObject();
        address.put("street", "123 Main St");
        address.put("city", "New York");
        address.put("zipCode", "10001");
        jsonObject.put("address", address);

        // JSON 객체 출력
        System.out.println(jsonObject.toJSONString());
    }
}

JSON 데이터와 Java 객체 간의 변환 기능을 제공하는 Codehaus 라이브러리 → jackson패키지 → ObjectMapper 클래스 사용

  • ObjectMapper를 사용하여 Java 객체를 JSON 문자열로 변환
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

public class JavaToJsonExample {
    public static void main(String[] args) throws Exception {
        // ObjectMapper 생성
        ObjectMapper objectMapper = new ObjectMapper();

        // 도메인 객체 생성
        MyDomainObject domainObject = new MyDomainObject();
        domainObject.setName("John");
        domainObject.setAge(30);

        // Java 객체를 JSON 문자열로 변환
				// writeValueAsString(Object value) 메소드사용, String return
        String jsonString = objectMapper.writeValueAsString(domainObject);

        // JSON 출력
        System.out.println(jsonString);
				/* 출력결
				{
				  "name" : "John",
				  "age" : 30
				*/

				//Java 객체의 필드를 JSON 문자열로 변환하며, 
				//이 결과는 JSON 객체의 키-값(key-value) 쌍 형식으로 저장 됨
				//각 필드는 JSON 객체의 키가 되고, 해당 필드의 값은 JSON 객체의 값으로 표현
    }
}

class MyDomainObject {
    private String name;
    private int age;

    // getter 및 setter 메서드

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
  • ObjectMapper를 사용하여 JSON 문자열을 Java 객체로변환
import com.fasterxml.jackson.databind.ObjectMapper;

public class JsonToJavaExample {
    public static void main(String[] args) throws Exception {
        // ObjectMapper 생성
        ObjectMapper objectMapper = new ObjectMapper();

        // JSON 문자열
        String jsonString = "{\"name\":\"John\",\"age\":30}";

        // JSON 문자열을 Java 객체로 변환
        MyDomainObject domainObject = objectMapper.readValue(jsonString, MyDomainObject.class);

        // Java 객체 사용
        System.out.println("Name: " + domainObject.getName());
        System.out.println("Age: " + domainObject.getAge());
				/* 출력결과
				Name: John
				Age: 30
				*/
    }
}
  • JSONValue를 사용하여 JSON문자열을 java 객체로 변환
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;

public class JSONValueToJSONObjectExample {
    public static void main(String[] args) {
        // JSON 문자열
        String jsonString = "{\"name\":\"John\",\"age\":30}";

        // JSON 문자열을 JSONValue로 파싱
				// parse메소드는 입력 소스에서 JSON 텍스트를 Java 객체로 구문 분석
        JSONValue jsonValue = JSONValue.parse(jsonString);

        // JSONValue를 JSONObject로 변환
        JSONObject jsonObject = (JSONObject) jsonValue;

        // JSONObject 사용 예제
				// get 메소드는 object를 return하기때문에 casting필
        String name = (String) jsonObject.get("name");
        Long age = (Long) jsonObject.get("age");

        // 결과 출력
        System.out.println("Name: " + name);
        System.out.println("Age: " + age);
    }
}

POINT 1 : JSON으로 데이터변환을 익혔다면 어떻게 전송할까??

  • REST(Representational State Transfer)
    • 웹 서비스 아키텍처 스타일 중 하나로, 분산된 시스템 간에 자원을 표현하고 전송하는 데 사용되는 아키텍처 스타일. REST는 웹 애플리케이션과 서비스 간의 통신을 위한 일반적인 원칙과 규칙을 정의
    1. 자원 (Resources): REST는 모든 것을 자원으로 간주. 자원에서 식별 가능한 모든 것을 의미하며, 각 자원은 고유한 URI(Uniform Resource Identifier)로 식별됨. 예를 들어, 웹 페이지, 이미지, 데이터베이스 레코드 등 모든 것이 자원이 될 수 있음.

    2. 표현 (Representation): 자원은 하나 이상의 표현을 가질 수 있음. 표현은 자원의 상태를 나타내며, 일반적으로 JSON 또는 XML 형식으로 표현됨. 클라이언트가 자원의 특정 표현을 요청하면 서버는 해당 표현을 반환한다.

    3. 상태 전이 (Stateless): REST는 상태를 관리하지 않는(stateless) 아키텍처 스타일임. 각 요청은 모든 필요한 정보를 포함하고 있어야 하며, 서버는 이 요청만으로 충분한 정보를 가지고 처리해야 한다. 이는 서버의 확장성을 향상시키고, 요청 간의 상태 의존성을 제거한다..

    4. HTTP 메서드 (HTTP Methods): REST는 HTTP 메서드(GET, POST, PUT, DELETE 등)를 사용하여 자원을 조작한다. 예를 들어, GET은 자원을 조회하고, POST는 자원을 생성하고, PUT은 자원을 업데이트하며, DELETE는 자원을 삭제하는 데 사용된다. 이는 CRUD를 의미한다.

    5. URI (Uniform Resource Identifier): 모든 자원은 고유한 URI로 식별된다. URI는 자원을 찾기 위한 주소 역할을 한다.

    6. 상호작용 (Interaction): REST 아키텍처는 클라이언트와 서버 간의 상호작용을 강조. 클라이언트가 자원을 요청하면 서버는 해당 자원의 상태를 클라이언트에게 전달하고, 클라이언트는 이를 기반으로 다음 요청을 수행한.

      Web Server로 잘 만들어진 platform을 활용하여 APP으로 전송한다.

      APP은 UI를 가지고있기때문에 client에 보낼 httpClient를 직접 생성해야한다.

      import org.apache.http.HttpEntity;
      import org.apache.http.HttpResponse;
      import org.apache.http.client.HttpClient;
      import org.apache.http.client.methods.HttpPost;
      import org.apache.http.entity.StringEntity;
      import org.apache.http.impl.client.HttpClients;
      import org.apache.http.util.EntityUtils;
      
      public class HttpClientPostExample {
          public static void main(String[] args) {
              // HttpClient 생성
              HttpClient httpClient = new DefaultHttpClient();
      
              // POST 요청 생성
      				// 원하는 POST 엔드포인트 URL로 변경
              HttpPost httpPost = new HttpPost("https://api.example.com/post-endpoint"); 
      
              try {
                  // 요청 헤더 설정 (예: Content-Type,Accept)
      						// Accept : 클라이언트가 선호하는 데이터 타입을 서버에게 알리는 데 사용
      						// Content-type : body의 타입을 서버에게 알리는 데 사용
      						// 이를통해 서버에서 JSON으로 Return 가능 
                  httpPost.setHeader("Content-Type", "application/json");
      						httpPost.setHeader("Accept", "application/json");
      
                  // 요청 바디 데이터 설정 (JSON 형식)
      						// 원하는 요청 데이터로 변경
                  String requestBody = "{\"key1\":\"value1\",\"key2\":\"value2\"}"; 
                  StringEntity requestEntity = new StringEntity(requestBody);
                  httpPost.setEntity(requestEntity);
      
                  // POST 요청 실행
                  HttpResponse response = httpClient.execute(httpPost);
      
                  // 응답 데이터 확인
                  if (response.getStatusLine().getStatusCode() == 200) {
      								// Response 중 Body를받는 getEntity메소드
                      HttpEntity responseEntity = response.getEntity();
                      String jsonResponse = EntityUtils.toString(responseEntity);
                      System.out.println("JSON 응답: " + jsonResponse);
      
                      // 여기에서 jsonResponse를 파싱하고 처리할 수 있.
                  } else {
                      System.out.println("HTTP 요청 실패: " + response.getStatusLine().getStatusCode());
                  }
              } catch (Exception e) {
                  e.printStackTrace();
              }
          }
      }

POINT 2 : UI를 만들었다면 Server에서는 요청을 어떻게 받을까?

  • 잘 만들어진 SpringFramework의 MVC를통해 요청과 응답을 처리

  • RESTController로 단일인입점처리를 통해 접근

  • 단어장

    • 렌더링(Rendering): parshing후 display
      • SSR(Server-Side-Rendering): 서버측에서 렌더링
      • CSR(Client-Side-Rendering): 클라이언트측에서 렌더링
    • 엔드포인트(end-point): 단일인입점
    • RESTfull API: 데이터의 CRUD 및 다양한 작업을 수행하기위해 제공하는 API

Question 1: 그렇다면 기존의 Contoller와 RESTController의 차이점은??

  1. 응답 형식:
    • Controller: 기존 @Controller 클래스는 HTML 뷰를 생성하거나 렌더링하여 HTML 페이지를 반환. 서버 측 렌더링(Server-Side Rendering)을 위해 사용됨.
    • RestController: @RestController 클래스는 주로 JSON 또는 XML과 같은 데이터 형식으로 데이터를 반환. RESTful API 엔드포인트(단일인입점)를 통해 클라이언트에게 데이터를 제공하는 데 사용.
  2. @ResponseBody 어노테이션:
    • Controller: 기존 @Controller에서 데이터를 응답으로 반환할 때는 @ResponseBody 어노테이션을 추가해야 한다. 이 어노테이션을 사용하면 메서드가 반환하는 데이터가 HTTP 응답 본문으로 직접 전송됨.
    • RestController: @RestController 클래스는 기본적으로 모든 메서드가 @ResponseBody 어노테이션을 가지고 있으므로, 메서드에서 반환하는 데이터는 자동으로 JSON 또는 XML로 직렬화되어 응답 본문으로 전송됨.
  3. 용도:
    • Controller: 기존 @Controller는 주로 웹 애플리케이션에서 HTML 페이지를 렌더링하거나 뷰 템플릿을 제공하는 데 사용됨.
    • RestController: @RestController는 주로 RESTful 웹 서비스 또는 API를 제공하는 데 사용됨. 클라이언트와의 데이터 교환을 위한 JSON 또는 XML 형식의 데이터를 반환.
  4. 미디어 타입 지정:
    • Controller: 기존 @Controller에서는 producesconsumes 매개변수를 사용하여 HTTP 요청 및 응답의 미디어 타입을 명시적으로 지정할 수 있음.
    • RestController: @RestController에서는 주로 JSON 미디어 타입을 사용하며, 별도의 미디어 타입 설정이 필요하지 않음.

요약하면, Controller는 주로 서버 측 렌더링을 위한 뷰 레이어를 처리하고 HTML 페이지를 생성하는 데 사용되며, RestController는 RESTful API를 구축하고 JSON 또는 XML과 같은 데이터 형식으로 데이터를 제공하는 데 사용됨.

Question 2: Contoller의 @RequestParam, @ModelAttribute 과 RESTController의 @ResponseBody의 차이점은??

@ResponseBody 어노테이션은 주로 JSON 또는 XML과 같은 데이터 형식으로 응답을 반환할 때 사용. 이 어노테이션을 사용하면 메서드가 반환하는 객체나 데이터가 직접 HTTP 응답 본문으로 변환되어 클라이언트에게 전송됨.

  1. 데이터 형식 지정: @ResponseBody를 사용하면 데이터를 특정 형식(예: JSON)으로 직렬화하고 응답 본문으로 제공. 이것은 RESTful API 또는 웹 서비스에서 데이터를 JSON 또는 XML 형식으로 반환해야 할 때 유용.
  2. 데이터 커스터마이징: @ResponseBody를 사용하면 데이터를 반환하는 과정을 커스터마이징 가능 예를 들어, JSON 데이터를 특정 필드만 포함하거나 특정한 형식으로 변환 가능.
  3. 단순화된 구현: @ResponseBody를 사용하면 데이터를 반환하는 데 필요한 코드를 단순화 가능. 객체나 데이터를 반환하면 Spring은 자동으로 해당 데이터를 JSON 또는 XML로 변환하고 응답 본문으로 설정.
  4. RESTful API 구축: RESTful API에서 클라이언트에게 데이터를 제공할 때 @ResponseBody를 사용하여 데이터를 응답 본문으로 반환하는 것이 일반적.

@RequestParam@ModelAttribute는 주로 요청 파라미터를 추출하거나 폼 데이터를 바인딩하는 데 사용되며, 주로 HTML 뷰를 렌더링할 때 또는 폼 데이터를 전송할 때 사용.

++ @PathVariable과 @RequestParam의 차이점 ++

@PathVariable는 /user/user19로 요청받은 URI를 /user/{userId}로 설정하여 {userId}를 받아 데이터타입에맞는 변수에 바인딩

@RequestParam은 key=value값을 받아옴

RESTController에서는 URI가 문자열로 넘어오기때문에 @PathVariable로 parshing하여 요청 수행

즉, 자바객체를받냐 JSON객체를 받냐 차

  • @RequestParam 사용 예제:
javaCopy code
@RestController
@RequestMapping("/example")
public class ExampleController {

    @GetMapping("/search")
    public ResponseEntity<String> search(@RequestParam String query) {
        // query 매개변수의 값을 사용하여 검색 작업을 수행
        return ResponseEntity.ok("Search query: " + query);
    }
}
  • @ModelAttribute 사용 예제:
javaCopy code
@RestController
@RequestMapping("/example")
public class ExampleController {

    @PostMapping("/add")
    public ResponseEntity<String> addUser(@ModelAttribute User user) {
        // User 객체를 받아서 데이터베이스에 추가하는 작업 수행
        return ResponseEntity.ok("Added user: " + user.getName());
    }
}
  • @PathVariable 사용 예제:
javaCopy code
@RestController
@RequestMapping("/example")
public class ExampleController {

    @GetMapping("/users/{userId}")
    public ResponseEntity<String> getUserById(@PathVariable Long userId) {
        // userId를 사용하여 특정 사용자의 정보를 조회하는 작업 수행
        return ResponseEntity.ok("User ID: " + userId);
    }
}
  • @RequestBody 사용 예제:
javaCopy code
@RestController
@RequestMapping("/example")
public class ExampleController {

    @PostMapping("/create")
    public ResponseEntity<String> createUser(@RequestBody User user) {
    // JSON 형식의 요청 본문에서 User 객체를 추출하여 데이터베이스에 추가하는 작업 수행
        return ResponseEntity.ok("Created user: " + user.getName());
    }
}

OPEN API를 사용하는 방법

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import org.json.JSONArray;
import org.json.JSONObject;

public class DataFetchAndParseExample {
    public static void main(String[] args) {
        try {
            // 외부 API의 URL
            String apiUrl = "https://api.example.com/data_endpoint";

            // URL 객체 생성
            URL url = new URL(apiUrl);

            // HTTP 연결 설정
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");

            // 응답 데이터 읽기
            BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            StringBuilder response = new StringBuilder();
            String line;

            while ((line = reader.readLine()) != null) {
                response.append(line);
            }
            reader.close();

            // JSON 데이터 파싱
            String responseData = response.toString();
            JSONObject jsonObject = new JSONObject(responseData);

            // JSON 객체에서 필요한 데이터 추출
            String key1 = jsonObject.getString("key1");
            int key2 = jsonObject.getInt("key2");

            JSONArray jsonArray = jsonObject.getJSONArray("key3");
            for (int i = 0; i < jsonArray.length(); i++) {
                JSONObject item = jsonArray.getJSONObject(i);
                String itemName = item.getString("itemName");
                int itemValue = item.getInt("itemValue");
                System.out.println("Item: " + itemName + ", Value: " + itemValue);
            }

            // 추출한 데이터 사용
            System.out.println("Key1: " + key1);
            System.out.println("Key2: " + key2);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

========================다음주 추가예정==========================

  1. 동기 / 비동기의 개념
  2. Jquery의 ajax를 활용한 RESTfull API적용
  3. React의 axios를 활용한 RESTfull API적용
profile
DevSecOps가 미래다

0개의 댓글