[Java] OPEN API 파싱하기 (JSON)

garam0410·2021년 4월 12일
8

Java 활용

목록 보기
1/3
post-thumbnail
post-custom-banner

OPEN API

API란, Application Programming Interface의 약자로, 응용 프로그램에서 사용할 수 있도록, 운영 체제나 프로그래밍 언어가 제공하는 기능을 제어할 수 있게 만든 인터페이스를 뜻한다.

OPEN API란, 사용자가 제공되는 데이터를 자유롭게 활용할 수 있도록 만들어놓은 인터페이스이다.

우리나라는 공공데이터 포털에서 각종 데이터들을 API형태로 제공해주고 있는데, 그 밖에 다양한 사이트에서도 제공해준다.

API로 제공되어지는 형태는 대부분 JSON이나 XML로 제공된다.

  • XML

  • JSON

데이터를 요청하면, 위 두형태로 결과를 얻을 수 있는데, 그냥 결과를 쓰기에는 어지럽고 지저분하다. 그래서 얻은 결과를 사용할 수 있도록 사용자가 가공하는 과정을 거쳐야한다.

이 포스트는 두가지 방식중에서 JSON에 대한것만 다루겠다.


JSON

JSON이란, JavaScript Object Notation의 약자로, key와 value 쌍으로 이루어진 형태의 object 이다.

위에 있는 JSON형태의 결과값을 보면

"resultCode" : "00"

을 볼 수가 있는데, 여기서 resultCode는 key, 00은 value가 된다. 이처럼 JSON은 key와 value로 구성되어 있다.

약자에 JavaScript 보면 알 수 있듯이, JavaScript에서 나온 포맷이다. 나는 JavaScript로 어플리케이션이 구성된 React Native라는 앱 개발 라이브러리를 사용해봤는데, 여기서 key와 value 처리가 . 하나로 가능했기 때문에 정말 편했다.

Java에서는 json 라이브러리를 따로 다운받아서 프로젝트에 import 해줘야 json을 처리할 수 있다.
위 링크에서 다운받아서 이클립스에 라이브러리를 추가후에 진행해야한다.


영화 상세정보 데이터 출력하기

나는 JSON 형태로 되어있는 영화 상세정보 데이터를 가공하여 콘솔에 출력해보았다.
영화 정보 데이터는 KOBIS에서 제공해주는 영화 상세정보 OPEN API를 사용하였다.

String key = "";    

String result = "";

먼저 데이터를 불러오기 위해서 사이트에서 제공 받은 API key를 key에 넣어준다. 아래에 있을 URL 부분에 넣어주어도 상관 없지만, 보기좋게 하기위해서 따로 변수를 선언해 주었다.

그리고 웹페이지에 나온 JSON 결과값을 저장할 변수인 result를 선언해준다.


try{
	URL url = new URL("http://www.kobis.or.kr/kobisopenapi/webservice/rest/movie/searchMovieInfo.json?key="
    				+ key + "&movieCd=20124039");
}catch(Exception e){
	e.printStackTrace();
}

다음은 URL 객체를 생성하기위해 위와 같이 작성해 준다. 예외처리를 위해서 try/catch 를 처리해준다. 저기에 있는 new URL() 안에는, 사이트에서 제공해주는 API 호출 URL을 넣어주는데, 앞서 선언해 주었던 API key를 위와 같이 추가해 준다.


BufferedReader bf;

bf = new BufferedReader(new InputStreamReader(url.openStream(), "UTF-8"));

result = bf.readLine();

URL 객체를 통해서 url을 연결했으면, 이제는 정말로 제공되어지는 원본데이터를 가져와야한다. 데이터를 모두 버퍼에 저장해서 하나의 데이터로 만들면, 입력 즉시 값이 전달되는 Scanner보다 빠른속도로 데이터를 처리할 수 있다. 양이 적다면 미미하겠지만, 가져올 데이터양이 많다면 차이가 많이 날수도 있기 때문에 입출력 라이브러리에서 BufferedReader 클래스를 사용할 것이다.

BufferedReader는 속성에 Reader 클래스가 오게 되는데, URL에서 제공되는 메소드인 openStream() 사용하기 위해서 InputStreamReader를 속성으로 사용한다. 간혹, 한글이 깨지는 경우가 있어서 UTF-8을 추가해주었다.

읽어온 Buffer 데이터를 readLine() 메소드를 사용해서 한줄씩 읽어, result변수에 저장한다. 이 때, result 변수를 출력해보면 정리되있지 않은 JSON 데이터를 불러온것을 확인할 수 있다.


JSONParser jsonParser = new JSONParser();
JSONObject jsonObject = (JSONObject)jsonParser.parse(result);
JSONObject movieInfoResult = (JSONObject)jsonObject.get("movieInfoResult");
JSONObject movieInfo = (JSONObject)movieInfoResult.get("movieInfo");

result 에 있는 값은 String 이다. 우리는 JSON 으로 인식하도록 바꾸기 위해서 앞서 불러왔던 JSON 관련 라이브러리를 사용할 것이다.

먼저 JSONParser를 사용해서 String 값을 JSON 객체로 만들어준다.
이 때, 만들어진 JSON 객체는 JSONObject 클래스를 사용해서 저장된다.
만들어진 JSONObject에서 key가 movieInfoResult 인 value를 추출하기 위해서 get() 을 사용한다.

그렇게 얻은 데이터에서 마지막으로 key가 movieInfo 인 value를 JSONObject에 다시 넣어주면 우리가 필요한 데이터를 나름(?) 잘 정리를 한 것이다.


System.out.println("영화코드 : " + movieInfo.get("movieCd"));
System.out.println("영화명(한글) : " + movieInfo.get("movieNm"));
System.out.println("영화명(영문) : " + movieInfo.get("movieNmEn"));
System.out.println("재생시간 : " + movieInfo.get("showTm"));
System.out.println("개봉일 : " + movieInfo.get("openDt"));
System.out.println("영화유형 : " + movieInfo.get("typeNm"));
System.out.println("제작국가명 : " + nations_nationNm.get("nationNm"));

이제 get() 을 사용해서 위처럼 출력만 해주면 된다.
그런데, 그림판으로 끄적인 사진을 보면, key와 value안에서 또다시 JSON 이 존재하는 것을 확인할 수 있다. 이때는, JSONArray 를 사용하여 내부 데이터를 Array 형태로 바꿔주고, 바뀐 Array 안의 index 마다 다시 JSONObject로 변환해준다. 그 뒤의 과정은 위에서 했던 것과 동일하다.


전체 소스

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;

public class movie {
    public static void main(String[] args) {
	
    	// 인증키 (개인이 받아와야함)
    	String key = "";

    	// 파싱한 데이터를 저장할 변수
    	String result = "";

    	try {

    		URL url = new URL("http://www.kobis.or.kr/kobisopenapi/webservice/rest/movie/searchMovieInfo.json?key="
    				+ key + "&movieCd=20124039");

    		BufferedReader bf;

    		bf = new BufferedReader(new InputStreamReader(url.openStream(), "UTF-8"));

    		result = bf.readLine();

        	JSONParser jsonParser = new JSONParser();
        	JSONObject jsonObject = (JSONObject)jsonParser.parse(result);
        	JSONObject movieInfoResult = (JSONObject)jsonObject.get("movieInfoResult");
        	JSONObject movieInfo = (JSONObject)movieInfoResult.get("movieInfo");

        	JSONArray nations = (JSONArray)movieInfo.get("nations");
        	JSONObject nations_nationNm = (JSONObject)nations.get(0);

        	JSONArray directors = (JSONArray)movieInfo.get("directors");
        	JSONObject directors_peopleNm = (JSONObject)directors.get(0);

        	JSONArray genres = (JSONArray)movieInfo.get("genres");

        	JSONArray actors = (JSONArray)movieInfo.get("actors");

        	System.out.println("영화코드 : " + movieInfo.get("movieCd"));
        	System.out.println("영화명(한글) : " + movieInfo.get("movieNm"));
        	System.out.println("영화명(영문) : " + movieInfo.get("movieNmEn"));
        	System.out.println("재생시간 : " + movieInfo.get("showTm"));
        	System.out.println("개봉일 : " + movieInfo.get("openDt"));
        	System.out.println("영화유형 : " + movieInfo.get("typeNm"));
        	System.out.println("제작국가명 : " + nations_nationNm.get("nationNm"));
       	
        	String genreNm = "";
       	
        	for(int i = 0; i < genres.size(); i++) {
            	JSONObject genres_genreNm = (JSONObject)genres.get(i);
            	genreNm += genres_genreNm.get("genreNm") + " ";
        	}

        	System.out.println("장르 : " + genreNm);
       	
        	System.out.println("감독명 : " + directors_peopleNm.get("peopleNm"));
       	
        	String peopleNm = "";
       	
        	for(int i = 0; i < actors.size(); i++) {
        		JSONObject actors_peopleNm = (JSONObject)actors.get(i);
        		peopleNm += actors_peopleNm.get("peopleNm") + " ";
        		peopleNm = peopleNm + actors_peopleNm.get("peopleNm") + " ";
        	}
       	
        	System.out.println("출연배우 : " + peopleNm);

    	}catch(Exception e) {
    		e.printStackTrace();
    	}
    }
}
post-custom-banner

4개의 댓글

comment-user-thumbnail
2022년 8월 30일

잘 배웠습니다!

답글 달기
comment-user-thumbnail
2022년 12월 13일

안녕하세요 덕분에 공부 잘 했습니다
궁금한게 있는데
System.out.println("장르 : " + genreNm);
이 부분에서 genreNm값은 어떻게 되는 건가요?

1개의 답글
comment-user-thumbnail
2023년 1월 17일

안녕 하세요
62년생 나이먹고 요즘
이런 머리아픈것에 관심이 생겻습니다
이렇게 공개해 주셔서 감사 합니다
천사표 하신김에 기왕이면
이거 php 웹페이지 로
출력 소스도 좀 만들어 주세요 ㅠㅠ

답글 달기