Json형식 String
으로 저장한다. // 1. URL을 만들기 위한 StringBuilder
StringBuilder urlBuilder = new StringBuilder("http://apis.data.go.kr/B552584/ArpltnInforInqireSvc/getCtprvnRltmMesureDnsty"); /*URL*/
// 2. 오픈 API의 요청 규격에 맞는 파라미터 생성
urlBuilder.append("?" + URLEncoder.encode("serviceKey","UTF-8") + "=ebZTQ4iRgDlaQNNtqJ5A9RcdWIhNzGvnQFQxLCwXDgjX/pNKJ49cQjal7Otx6mIyZpr/GWQWvwieBTwSMcb40w=="); /*Service Key*/
urlBuilder.append("&" + URLEncoder.encode("returnType","UTF-8") + "=" + URLEncoder.encode("json", "UTF-8")); /*xml 또는 json*/
urlBuilder.append("&" + URLEncoder.encode("numOfRows","UTF-8") + "=" + URLEncoder.encode("100", "UTF-8")); /*한 페이지 결과 수*/
urlBuilder.append("&" + URLEncoder.encode("pageNo","UTF-8") + "=" + URLEncoder.encode("1", "UTF-8")); /*페이지번호*/
urlBuilder.append("&" + URLEncoder.encode("sidoName","UTF-8") + "=" + URLEncoder.encode("서울", "UTF-8")); /*시도 이름(전국, 서울, 부산, 대구, 인천, 광주, 대전, 울산, 경기, 강원, 충북, 충남, 전북, 전남, 경북, 경남, 제주, 세종)*/
urlBuilder.append("&" + URLEncoder.encode("ver","UTF-8") + "=" + URLEncoder.encode("1.0", "UTF-8")); /*버전별 상세 결과 참고*/
// 3. URL 객체 생성 (String으로 변환)
URL url = new URL(urlBuilder.toString());
// 4. 요청하고자 하는 URL과 통신하기 위한 Connection 객체 생성
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// 5. 통신을 위한 메소드 세팅 ("GET")
conn.setRequestMethod("GET");
// 6. 통신을 위한 Content-type 세팅 ("JSON" 으로 해야함 - reuslt의 값은 String이기 때문에)
conn.setRequestProperty("Content-type", "application/json");
// 7. 통신 응답 코드 확인
System.out.println("Response code: " + conn.getResponseCode());
// 8. 전달받은 데이터를 BufferedReader 객체로 저장. 오류가 날 경우 error발생
BufferedReader rd;
if(conn.getResponseCode() >= 200 && conn.getResponseCode() <= 300) {
rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
} else {
rd = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
}
// 9. 저장된 데이터를 라인별로 읽어 StringBuilder 객체로 저장
StringBuilder sb = new StringBuilder();
String line;
while ((line = rd.readLine()) != null) {
sb.append(line);
}
// 10. 객체 해제
rd.close();
conn.disconnect();
적절한 데이터로 가공하고 사용하기 위해 DTO 로 개발!
즉, JSON Parsing 과정이 필요하다.
이걸 왜 파싱해?간단하죠. 저희는 이렇게 JSON형태로 온 데이터들을 파싱, 음..데이터를 뽑아낸다고 말하는게 좋을까요?저 형태로는 저 데이터들을 이용할 수 없으니까요. 우리는 저기서 데이터들을 뽑아서 아 이름이 테스트고, 나이가 25고.. 배열 또는 딕셔너리 형태로 저장해야 저 데이터들을 쓸 수 있겠죠?그래서 다들 JSON 파싱 파싱 그러는거랍니다.
출처: https://zeddios.tistory.com/90 [ZeddiOS:티스토리]
String jsonString = sb.toString();
// 11. 결과 출력
// System.out.println(jsonString);
log.warn("진입1");
log.info(jsonString);
// 12. 해야할 것 -> 데이터 사용하려면 적절하게 가공해야함
// 입력이 Json 형테의 String으로 들어오는 상황. -> Json파싱 필요
// JSONParser, gson, ObjectMapper등을 사용하여 변환가능.
jsonParser2(jsonString);
public void jsonParser2(String jsonString) throws ParseException {
log.info("진입2");
// 1. 문자열 형태의 JSON을 파싱하기 위한 JSONParser 객체 생성
JSONParser parser = new JSONParser();
// 2. 문자열을 JSON 형태로 JSONObject 객체에 저장
JSONObject obj = (JSONObject)parser.parse(jsonString);
// 3. 필요한 리시트 데이터 부분만 가져와 JSONArray로 저장
JSONArray dataArr = (JSONArray)obj.get("data");
// 4. 출력 확인
System.out.println(dataArr.toString());
}
해당 과정을 했을때의 에러코드이다.
잘보면 String 으로는 잘 들어왔다.
그러나 dataArr에는 null이 들어왔단다.
이유가 뭘까?
https://velog.io/@yeonn1006/Cannot-invoke-org.json.simple.JSONArray.size-because-array-is-null
바로 제공되는 step에 따라 Mapping을 해주지 않았기때문!
우리는 제공해주는 Data의 스텝을 지켜주면서 데이터를 받아와야만한다.
해당 부분을 고쳐서 해보자.
try{
// 1. 문자열 형태의 JSON을 파싱하기 위한 JSONParser 객체 생성.
JSONParser parser = new JSONParser();
// 2. 문자열을 JSON 형태로 JSONObject 객체에 저장.
JSONObject obj = (JSONObject)parser.parse(jsonString);
JSONObject responseResult = (JSONObject)obj.get("response");
JSONObject headerResult = (JSONObject)responseResult.get("header");
JSONObject bodyResult = (JSONObject)responseResult.get("body");
JSONObject itemsResult = (JSONObject)bodyResult.get("items");
JSONArray itemResult = (JSONArray) itemsResult.get("item");
for (Object item : itemResult) {
log.info(item.toString());
}
} catch (ParseException e) { System.out.println(e.getMessage()); }
잘 될줄 알았는데 이게 웬걸.
난데없는 아래와 같은 에러가 발생했다.
에러를 살펴보니 JSONArray는 Object로 캐스팅 할 수 없단다!
java.lang.ClassCastException: class org.json.simple.JSONArray cannot be cast to class org.json.simple.JSONObject
데이터가 잘못됐나? 찾아보니,
여기서 xml 데이터로 확인했을 때, items 라는 Object 안에item배열이 있는 줄 알았다.
해당 Open API 데이터는 items 라는 배열안에 item Object들이 모여있었다!
즉, 배열 안에 오브젝트가 있다는 것.
try{
// 1. 문자열 형태의 JSON을 파싱하기 위한 JSONParser 객체 생성.
JSONParser parser = new JSONParser();
// 2. 문자열을 JSON 형태로 JSONObject 객체에 저장.
JSONObject obj = (JSONObject)parser.parse(jsonString);
JSONObject responseResult = (JSONObject)obj.get("response");
JSONObject headerResult = (JSONObject)responseResult.get("header");
JSONObject bodyResult = (JSONObject)responseResult.get("body");
JSONObject itemsResult = (JSONArray)bodyResult.get("items"); //Object가 아닌, Array
// JSONArray itemResult = (JSONArray) itemsResult.get("item"); 해당부분 제거
// Array속 Object를 꺼내오려면 이렇게 !
for(int i=0; i<itemsResult.size(); i++){
JSONObject getItem = (JSONObject) itemsResult.get(i); //Object 추출
log.info((String)getItem.get("pm10Value"));
}
} catch (ParseException e) { System.out.println(e.getMessage()); }