20220930 [Spring Boot, API, XML to JSON]

Yeoonnii·2022년 10월 5일
0

TIL

목록 보기
38/52
post-thumbnail

API로 데이터 가져오기

외부 api = 지도, 소셜로그인, 공공DB, 결제, 페이//…
외부 API의 형태

  • json = xml보다 용량이 작고 구조가 단순
  • xml = json보다 용량이 크다
    xml 형태를 받아와서 json 형태로 변환하면 된다
    변환된 JSON형태를 꺼내어 사용하면 된다

데이터를 DB에 저장할때 제일좋은 방법은
해당 데이터의 entity를 만들어 넣는것이다
➡️ 조금 번거로울 수는 있다

RestController에서 Spring boot에서 제공하는 RestTemplate을 사용하여 API 가져오기

pom.xml

json문서 파싱을 위한 라이브러리 설치

<!-- json문서 파싱을 위한 라이브러리 -->
			<dependency>
		<groupId>org.json</groupId>
		<artifactId>json</artifactId>
		<version>20211205</version>
	</dependency>

1. JSON API 가져오기

API 예시 http://1.234.5.158:13000/json/exam1.json

🛠 로직
1. api호출하여 결과를 가져오기
➡️ 대부분의 API는 get형태가 많다 = 정보를 가져오거나 받아오는 형태
2. 가져온 데이터를 반환해준다
3. DB에 저장해준다

Spring boot에서 제공하는 RestTemplate을 사용하여 API를 가져온다
RestTemplate.getForObject(URI url, Class<T> responseType) => (호출하는 url, 반환타입)

ApiRestController.java

데이터를 컨트롤러에 넣을 수 있어야 DB에 저장이 가능하다

    // JSON형태의 api받아오기
    // 127.0.0.1:8080/BOOT1/api/exam1.json
    @GetMapping(value = "/exam1.json")
    public Map<String, Object> exam1GET() {
        Map<String, Object> map = new HashMap<>();
        try {
            // 소셜 로그인 , 공공api 등의 url
            String url = "http://1.234.5.158:13000/json/exam1.json";

            // Spring boot에서 제공하는 RestTemplate
            RestTemplate restTemplate = new RestTemplate();
            
            // 1. api호출하여 결과를 가져오기
            // RestTemplate.getForObject(URI url, Class<T> responseType) => (호출하는 url, 반환타입)
            String response = restTemplate.getForObject(url, String.class);

            // 2. 가공된 데이터를 반환
            System.out.println(response);

            // 3. DB에 저장
            // {"ret" : "y", "data":"123"}
            JSONObject jobj = new JSONObject(response.toString());

            String ret1 = jobj.getString("ret"); // y
            String ret2 = jobj.getString("data"); // 123

            System.out.println(ret1 + "," + ret2);

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

결과화면


2. 배열형태의 XML API를 Map에 담기

API 예시 http://1.234.5.158:13000/xml/exam1.xml

🛠 로직
1. api호출하여 결과를 가져오기
➡️ 대부분의 API는 get형태가 많다 = 정보를 가져오거나 받아오는 형태
2. 가져온 데이터를 가공하여 반환해준다
3. DB에 저장해준다

ApiRestController.java

// XML형태의 api받아오기
    // 127.0.0.1:8080/BOOT1/api/exam100.json
    @GetMapping(value = "/exam100.json")
    public Map<String, Object> exam100GET() {
        Map<String, Object> map = new HashMap<>();
        try {
            // 소셜 로그인 , 공공api 등의 url
            String url = "http://1.234.5.158:13000/xml/exam1.xml";

            // Spring boot에서 제공하는 RestTemplate
            RestTemplate restTemplate = new RestTemplate();
            
            // 1. api호출하여 결과를 가져오기
            // 대부분의 api는 get형태가 많다 = 정보를 가져오거나 받아오는 형태
            // RestTemplate.getForObject(URI url, Class<T> responseType) => (호출하는 url, 반환타입)
            String response = restTemplate.getForObject(url, String.class);

            // XML을 JSON Object로 변환하기
            JSONObject jobj = XML.toJSONObject(response);

            // 변환된 데이터 확인
            // {"response":{"items":{"item":[{"name":"one","id":1},{"name":"two","id":2},{"name":"three","id":3}]}}}
            System.out.println("--------------jobj.toString---------------");
            System.out.println(jobj.toString());

            // 3. 데이터에서 꺼내어쓰기
            JSONObject jobj1 = jobj.getJSONObject("response").getJSONObject("items");

            // {"item":[{"name":"one","id":1},{"name":"two","id":2},{"name":"three","id":3}]}
            System.out.println("--------------jobj1---------------");
            System.out.println(jobj1.toString());

            // 배열 형태이니 반복문을 이용
            // [
            // {"name":"one","id":1},
            // {"name":"two","id":2},
            // {"name":"three","id":3}
            // ]

            JSONArray jarr = jobj1.getJSONArray("item");
            System.out.println(jarr.length());
            for (int i = 1; i < jarr.length(); i++) {
                // {"name":"one","id":1}
                String name = jarr.getJSONObject(i).getString("name");
                int id = jarr.getJSONObject(i).getInt("id");
            }

            System.out.println("--------------jarr---------------");
            System.out.println(jarr);

            // map.put("jobj", jobj.toString());

            // String ret1 = jobj.getString("items"); //y
            // String ret2 = jobj.getString("data"); //123

            // System.out.println(ret1 + "," + ret2);

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

3. 배열형태의 JSON API를 map에 담기

API 예시 http://1.234.5.158:13000/json/exam2.json

배열형태의 JSON API 받아오기
배열형태의 데이터는 DTO생성하고 넣는게 좋다

row 는 [ ]형태 변수 하나를 갖는다
row를 Exam2DTO로 꺼내고
row안의 Exam1DTO형태의 2개의 object를 꺼냄

받아온 API의 형태가 JSON형태라면 바로 DTO에 넣으면 되는데
xml형태인 경우
⇒ String 으로 먼저 받고 수동으로 json형태로 변환해주거나
⇒ String 으로 먼저 받고 json형태로 변환 후 map에 넣어 DTO에 담아줄 수 있다

xml을 DTO에 넣는경우에는 DTO로 바로 받을 수 없으며
map으로 변환하는 수동작업이 필요하다

2. 배열형태의 XML API를 Map에 담기 방법으로 수동으로 map으로 넣어주면 된다
⇒ 코드 양이 길어지는 단점이 있다

이때 받아온 데이터를 전부 DTO로 바꾸는게 아니라
map에 필요한 데이터만 저장하여 DTO에 넣어 사용하거나 화면에 출력한다

꼭 restcontroller 에서만 API를 받아오는게 아니라 controller에서 API를 받아와서 view에 출력이 가능하다

🛠 로직
1. api호출하여 결과를 가져오기
➡️ 대부분의 API는 get형태가 많다 = 정보를 가져오거나 받아오는 형태
2. Exam2DTO의 형태로 먼저 꺼내온다
3. response.getRow()만큼 반복문을 실행하여
3. map에 담아 반환해준다

dto/Exam2DTO.java

여러개의 Exam1DTO = List<Exam1DTO> row를 가지는 Exam2DTO를 생성해준다

package com.example.dto;

import java.util.List;

import lombok.Data;

@Data
public class Exam2DTO {
    List<Exam1DTO> row;
}

dto/Exam1DTO.java

row안 배열 형태를 확인하여 DTO를 생성해준다

package com.example.dto;

import lombok.Data;

@Data
public class Exam1DTO {
    String ret;
    String data;
}

ApiRestController.java

    // 127.0.0.1:8080/BOOT1/api/exam2.json
    // 이 방법이 제일 간편!
    @GetMapping(value = "/exam2.json")
    public Map<String, Object> exam2GET() {
        Map<String, Object> map = new HashMap<>();
        try {
            // 소셜 로그인 , 공공api 등의 url
            String url = "http://1.234.5.158:13000/json/exam2.json";

            // Spring boot에서 제공하는 RestTemplate
            RestTemplate restTemplate = new RestTemplate();
            // 1. api호출하여 결과를 가져온 다음
            // 대부분의 api는 get형태가 많다 = 정보를 가져오거나 받아오는 형태
            // RestTemplate.getForObject(URI url, Class<T> responseType) => (호출하는 url, 반환타입)

            // Exam2DTO의 형태로 먼저 꺼내온다
            Exam2DTO response = restTemplate.getForObject(url, Exam2DTO.class);

            // Exam2DTO의 getRow()를 꺼낸다 => List<Exam1DTO> 타입
            for (Exam1DTO obj : response.getRow()) {
                // Exam1DTO(ret=y1, data=123)
                // Exam1DTO(ret=y2, data=234)
                System.out.println("============");
                System.out.println(obj.toString());
            }

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

출력결과


4. 배열형태의 JSON API를 DTO에 담기

API 예시 http://1.234.5.158:13000/json/exam2.json

🛠 로직
1. api호출하여 결과를 가져오기
➡️ 대부분의 API는 get형태가 많다 = 정보를 가져오거나 받아오는 형태
2. XML을 String 형태로 먼저 받아오기
3. JSON객체로 변환해주기
4. 변환된 JOSON객체를 map에 담은 후 DTO와 매칭하여 변환하기
convertValue(json.toMap(), Exam2DTO.class) ➡️ map을 DTO와 매칭

ApiRestController.java

// map을 이용해 DTO에 넣어주기
    // 127.0.0.1:8080/BOOT1/api/exam200.json
    @GetMapping(value = "/exam200.json")
    public Map<String, Object> exam200GET() {
        Map<String, Object> map = new HashMap<>();
        try {
            // 소셜 로그인 , 공공api 등의 url
            String url = "http://1.234.5.158:13000/json/exam2.json";

            // Spring boot에서 제공하는 RestTemplate
            RestTemplate restTemplate = new RestTemplate();

            // 1. api호출하여 결과를 가져온 다음
            // 대부분의 api는 get형태가 많다 = 정보를 가져오거나 받아오는 형태
            // RestTemplate.getForObject(URI url, Class<T> responseType) => (호출하는 url, 반환타입)

            // 2. String형태로 먼저 받기
            String response = restTemplate.getForObject(url, String.class);

            // 3. JSON객체로 변환
            JSONObject json = new JSONObject(response);

            // map => DTO로 변환
            // json.toMap(), Exam2DTO.class => map을 dto와 매칭
            // [Exam1DTO(ret=y1, data=123), Exam1DTO(ret=y2, data=234)]
            ObjectMapper mapper = new ObjectMapper();
            Exam2DTO exam2 = mapper.convertValue(json.toMap(), Exam2DTO.class);
            System.out.println(exam2.getRow().toString());

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

출력결과


5. 외부 API로 값을 전달해주는 경우(결제 등)

API 예시 http://1.234.5.158:13000/json/post1.json

dto/Exam1DTO.java

값을 전달해 줄 DTO를 생성한다

package com.example.dto;

import lombok.Data;

@Data
public class Exam1DTO {
    String ret;
    String data;
}

ApiRestController.java

데이터를 post방식으로 전송 ➡️ map형식이 데이터를 많이 전송 할 수 있다

    // 127.0.0.1:8080/BOOT1/api/post1.json
    // 외부 api사용하여 데이터 전달하는 경우 = post사용해야 한다
    @GetMapping(value = "/post1.json")
    public Map<String, Object> getMethodName() {
        Map<String, Object> map = new HashMap<>();
        try {
            String url = "http://1.234.5.158:13000/json/post1.json";

            // ret, data의 정보를 post방식으로 전송
            // map형식이 데이터를 많이 전송 할 수 있다
            Map<String, Object> param = new HashMap<>();
            param.put("ret", "999");
            param.put("data", "000");

            // Spring boot에서 제공하는 rest템플릿
            RestTemplate restTemplate = new RestTemplate();

            // DTO로 받기, 구조가 복잡하면 String으로 받아서 수동으로 파싱하기
            Exam1DTO response = restTemplate.postForObject(url, param, Exam1DTO.class);
            System.out.println(response);

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

출력결과


6. 배열형태의 JSON API를 DTO에 담기

DTO 생성하여 가져온 API 보관하기

API 예시 http://1.234.5.158:13000/board101/select.json?text=&page=1

dto/BoardSelectDTO2.java

BoardSelectDTO2BoardSelectDTO형태를 List로 가지고 있으며,
변수 status와 total을 가지고 있다

package com.example.dto;

import java.util.List;

import lombok.Data;

@Data
public class BoardSelectDTO2 {
    int status;
    List<BoardSelectDTO> rows;
    Long total;
}

dto/BoardSelectDTO.java

날짜형태를 가져올때
1. 먼저 String 타입으로 지정하여 데이터를 가져온다
2. String으로 가져온 날짜 데이터를 Date 형태로 알맞게 형변환 시켜준다
➡️ String 형태의 날짜 정보를 적절한 pattern에 맞게 적용하여 Date로 변환해준다!

package com.example.dto;

import java.util.Date;

import com.fasterxml.jackson.annotation.JsonFormat;

import lombok.Data;

@Data
public class BoardSelectDTO {
    Long _id;
    String title;
    String writer;
    Long hit;
    // // 날짜는 일단 String 타입으로 잡고 형변환 시킨다
    // String regdate;

    // String 으로 되어있는 날짜 정보를 pattern에 맞게 적용하여 Date로 변환
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    Date regdate;
}

ApiRestController.java

데이터를 컨트롤러에 넣을 수 있어야 DB에 저장이 가능하다

    // Board1DTO를 만들어서 보관하기
    // String url ="http://1.234.5.158:13000/board101/select.json?text=&page=1";
    // 127.0.0.1:8080/BOOT1/api/select.json
    @GetMapping(value = "/select.json")
    public Map<String, Object> selectGET(
    ){
        Map<String, Object> map = new HashMap<>();
        try {
            String url = "http://1.234.5.158:13000/board101/select.json?text=&page=1";

            // Spring boot에서 제공하는 RestTemplate
            RestTemplate restTemplate = new RestTemplate();
            
            BoardSelectDTO2 response = restTemplate.getForObject(url, BoardSelectDTO2.class);
            // System.out.println(response.toString());
            
            for (BoardSelectDTO obj : response.getRows()) {
                obj.setTitle( obj.getTitle() + "변경된 내용추가" );
                System.out.println(obj.toString());
            }

            map.put("status", response.getStatus());
            map.put("total", response.getTotal());
            map.put("rows", response.getRows());

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

출력결과

0개의 댓글