본문 바로가기
BE/Java

외부 API 파싱하기 (JSON)

by cjsrhd94 2022. 2. 7.

기업 협업 프로젝트중 농장 실사 방문 예약 기능을 만들 일이 있었다. 기업의 요구사항으로 기업측에서 하루에 한 농가만 방문할 수 있게 예약 시스템을 구현해야했다. 이에 농장 입점 신청자가 입점 3단계를 시작하면 서버에서 예약 불가능한 날짜를 return해주어야 했다.

예약 불가능한 날짜 중 주말은 자체적으로 구현할 수 있었지만, 공휴일은 자체적으로 구현하는 것이 효율적이지 않다고 생각했다. 이에 공공데이터 포털에서 제공하는 한국천문연구원_특일 정보를 활용하기로 했다.

 

API 파싱하기

우선 공공데이터포털 사이트에 들어가 로그인 후 API 사용 신청을 해주어야한다.

사용신청을 완료하면 위와 같은 화면을 볼 수 있다. 여기서 우리는 일반 인증키(Encoding)를 복사하여 아래 코드의 '서비스키' 에 붙여넣기 해준다.

// HolidayApi.java

public class HolidayApi {
    public static void main(String[] args) throws Exception {
    	// 1. 서버에 요청할 url을 만든다.
        StringBuilder urlBuilder = new StringBuilder("http://apis.data.go.kr/B090041/openapi/service/SpcdeInfoService/getRestDeInfo"); /*URL*/
        urlBuilder.append("?" + URLEncoder.encode("serviceKey", "UTF-8") + "=서비스키"); /*Service Key*/
        urlBuilder.append("&" + URLEncoder.encode("pageNo", "UTF-8") + "=" + URLEncoder.encode("1", "UTF-8")); /*페이지번호*/
        urlBuilder.append("&" + URLEncoder.encode("numOfRows", "UTF-8") + "=" + URLEncoder.encode("62", "UTF-8")); /*한 페이지 결과 수*/
        urlBuilder.append("&" + URLEncoder.encode("solYear", "UTF-8") + "=" + URLEncoder.encode("2022", "UTF-8")); /*연*/
        urlBuilder.append("&" + URLEncoder.encode("solMonth", "UTF-8") + "=" + URLEncoder.encode("02", "UTF-8")); /*월*/
        urlBuilder.append("&" + URLEncoder.encode("_type","UTF-8")+ "=" + URLEncoder.encode("json"));

        // 2. url 객체를 만들고, Http 헤더에 필요한 정보들을 포함시켜 커넥션 객체를 생성하고 연결한다.
        URL url = new URL(urlBuilder.toString());
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        conn.setRequestProperty("Content-type", "application/json");
        System.out.println("Response code: " + conn.getResponseCode());

        // 3. 응답 코드에 따라서 데이터를 받아오거나, 에러메시지를 받아온다.
        BufferedReader rd;
        if (conn.getResponseCode() >= 200 && conn.getResponseCode() <= 300) {
            rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        } else {
            rd = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
        }

        // 4. String 형태로 데이터를 받아오고 커넥션을 끊어준다.
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = rd.readLine()) != null) {
            sb.append(line);
        }
        rd.close();
        conn.disconnect();
        System.out.println(sb.toString());

        // 5. String 형태의 데이터를 Json 형태로 파싱한다.
        JSONParser jsonParser = new JSONParser();
        JSONObject jsonObject = (JSONObject) jsonParser.parse(sb.toString());
        JSONObject parseResponse = (JSONObject) jsonObject.get("response");
        JSONObject parseBody = (JSONObject) parseResponse.get("body");
        JSONObject parseItems = (JSONObject) parseBody.get("items");
        JSONArray parseItem = (JSONArray) parseItems.get("item");

        JSONObject item;
        for (Object parse : parseItem) {
            item = (JSONObject) parse;
            Long locdate = (Long) item.get("locdate");
            String dateName = (String) item.get("dateName");
            
            System.out.println("dataName: " + dateName + ", locdate: " + locdate);
        }
    }    
}

프로젝트에 사용했던 코드중 일부를 가져왔다. 각각의 단계에서 어떤 작업이 진행되는지 주석을 달아두었다.

서버에서 받아온 데이터는 위 사진과 같은 구조를 가지고 있다. 이에 우리는 JSON형태의 문자열을 파싱해 필요한 정보를 추출해야 한다. 객체 형태의 데이터는 JSONObject를 사용해 내부 데이터를 Object로 만들어 줄 수 있다.  배열 형태의 데이터는 JSONArray를 사용해 내부 데이터를 Array로 만들어 줄 수 있다.

위의 경우 우리가 원하는 정보는 response 객체 - body 객체 - items 객체 - item 배열로 존재하기 때문에, JSONObject - JSONObject - JSONObject - JSONArray 를 사용해 파싱하였다.

이후 파싱된 배열에서 필요한 정보들을 추출해 for문을 돌려보면 위와 같은 데이터를 얻을 수 있다.

댓글