JavaScript 활용팁
2019.05.29 / 24:28

[파싱] 2. JSON 다운로드 및 기본적인 구조 익히기

탁돌이개발자
추천 수 71

JSON 파싱을 이용하려면 JSON라이브러리를 포함시켜주어야 한다. 물론 본인이 직접 JSON 파싱에 필요한 클래스나 메소드를 전부 만들수도 있지만 그건 말그대로 시간낭비에 가깝다. 이미 만들어져있는 라이브러리가 있는데 그걸 또 만들 필요는 없다. 실력향상을 위해 만들어 연습하는거라면 얘기가 달라지지만 우리는 파싱을 목적으로 하는 것이기 때문에 만들어져 있는 표준화된 JSON을 이용하도록 한다.

우선 구글에서 배포중인 simple json을 다운받는다.


이후 다운로드한 json-simple-1.1.1.jar 파일을 이클립스에서 라이브러리 추가를 해준다.

여기까지 했으면 JSON을 사용할 준비는 끝난것이다.

JSON을 분석하기에 앞서 이 한가지를 반드시 기억해 놓길 바란다
"JSON은 Map 구조이다."
Map구조란 자료구조에서 key와 value를 같이 저장해 놓는 방식을 의미한다. 즉, 회원관리를 예를 들어보면 id:test를 key로, pw:1234를 value로 하여 둘을 1쌍으로 묶어 관리하는 방식이다.

이를 염두에 두고 이제 기본적인 JSON의 구조를 분석해보자

{"univ":{"professor":"김교수","student":"이학생"}}

이게 바로 JSON을 파싱했을때 받을 수 있는 결과이다. 물론 이렇게 단순하게 결과가 나오는 경우는 절대 없다. 그러나 기본적인 구조는 크게 변하지 않으니 쉬운 예제부터 분석해보자

그런데 이런 짧은 코드는 크게 문제가 되질 않으나 코드가 길어지게 되면 알아보기가 힘들다. 따라서 이 코드를 가독성을 높여 표현하면 다음과 같다.

{ "univ":{ "professor":"김교수", "student":"이학생" } }

이제는 알아보기 한결 더 수월할 것이다. 
아까도 얘기했듯이 Map구조기 때문에 key:value 구조로 저장된다. 이에 맞춰 보면 professor라는 key와 김교수라는 value가 쌍으로 저장되고, student라는 key와 이학생이란 value가 같이 쌍으로 되는 것이다. 
바깥고리도 보면 univ라는 key와 professor, student를 포함하는 { } 내부가 value로 엮여 한쌍으로 저장되는 것이다.

그러면 여기서 우리가 파싱해와야 할 최종 목표값은 professor와 student의 정보라고 잡자. 그러면 바로 저 값에 접근할 수 있을까? 답은 아니다.
professor와  student는 univ의 value로 묶여 저장되어 있는 것이기 때문에 univ부터 파싱하여 먼저 접근한 다음 professor와 student의 값을 받아올 수 있는 것이다.

이제 직접 코드를 짜서 설명을 해 보겠다.
아까 라이브러리를 추가 했으니 이번엔 사용할 라이브러리들을 import해주어야 한다.

import org.json.simple.JSONObject; //JSON객체를 만드는데 사용 import org.json.simple.parser.JSONParser; //JSON객체를 파싱해오는데 사용 import org.json.simple.parser.ParseException; //예외처리

그리고 예제 코드를 클래스를 생성하여 직접 JSON에 추가시켜준다.

class JSONAdd{ String json; //JSON객체를 전달해 주기 위한 String void jsonadd(){ JSONObject inner = new JSONObject(); //내부 inner.put("professor", "김교수"); //(key="professor" : value="김교수") 둘다 String inner.put("student", "이학생"); //(key="student" : value="이학생") 둘다 String JSONObject outer = new JSONObject(); //외부 outer.put("univ", inner); //(key="univ" : value=inner) String, 객체 타입 json = outer.toJSONString();//최종적으로 만들어진 json객체를 String으로 변환하여 저장 //outer를 넣어서 객체를 그대로 뽑아도 출력은 되나, 가급적 형변환 하는것을 권장 System.out.println(json); } }

생각보다 간단하니 겁먹지 말길 바란다. 우선 데이터를 만드는데있어 JSON은 내부 -> 외부 순으로 만들어준다.
따라서 내부 JSON객체를 inner로 선언해주고, 내부에 있던 professor와 student의 정보를 inner에 넣어준다. 
그리고 외부 JSON객체를 outer로 선언하고, outer에 univ에 inner를 한 쌍으로 넣어준다.
여기서 알 수 있듯이 JSON객체는 말그대로 Object타입과 유사한 객체이기 때문에  key와 value에는 String, int 등을 포함하여 객체들 까지도 저장이 가능하다.(제너릭스는 사용 불가)
이렇게 만들어진 outer라는 최종 결과물을 .toJSONString()을 통해 String 타입으로 캐스팅 후 json에 저장해준다.(결국 json에 저장된 정보가 최종 파싱 대상이 되므로 반드시 필요한 과정이다.)

이제 이렇게 JSON을 만드는 클래스를 메인메소드에서 호출해보면 출력이 다음과 같이 된다.

위에서 보았던 예제 그대로이다.
이제 이렇게 만들어진 JSON객체를 파싱하여 professor와 student의 정보만 가져와 보도록 하겠다.

메인메소드에서 먼저 Exception처리를 해준다. 파싱과정에서 당연히 잘못 불러올 수도 있고 이는, 런타임에러와 같은 unchecked error가 아닌 별도 예외처리가 필요한 checked error이므로 throws ParseException이나 try...catch를 해준다.

public class Main{ public static void main(String[] args) throws ParseException { JSONAdd jsonAdd = new JSONAdd(); jsonAdd.jsonadd(); //이전에 만든 JSON추가 클래스를 불러옴 } }

여기까지해서 기본 과정이 끝났으면 이제 JSONParser parser = new JSONParser();를 선언하여 파싱 작업을 하는 객체를 만들어준다.

JSONParser parser = new JSONParser();

이제 String json을 저 parser를 통해 파싱받은 뒤, JSON오브젝트 형태로 저장한다.

JSONObject obj = (JSONObject)parser.parse(jsonAdd.json);

여기서 obj객체는 결국 위의 내용 전체를 파싱한 결과를 담고 있는 것이다. 여기선 전부라 해봤자 outer와 outer내부의 inner밖에 없으니 결국 obj = outer와 같은 상태이다.

그럼 이렇게 obj에 담긴 전체 정보 중 먼저 univ에 접근하여 데이터를 받아온다.

JSONObject univ = (JSONObject)obj.get("univ");

obj가 결국 outer라고 했으니 outer내부에는 univ : {...} 이런 식으로 정보들이 담겨있는 상태이다. 우리는 여기서 univ라는 새로운 univ라는 JSON객체를 선언하고, obj에서 "univ"라는 key와 일치하는 정보를 받아와 JSON오브젝트로 형변환 후 직전에 선언한 univ라는 객체에 담아준다.

사실 JSON생성 클래스의 내용들과 이름이 중복이라 헷갈릴 수도 있지만, 일반적으로 JSON파싱을 진행할 땐, 웹에서 받아오기 때문에 이런식으로 이름을 같이 해주는게 오히려 더 알아보기 쉽다.
이제 그러면 제대로 univ에 내용들이 담겨있는지 출력해서 확인해 보면 아래와 같다.

System.out.println(univ.toJSONString());

잘 담겨있다. 이런식으로 출력문을 통해 확인을 수시로 해주면 꼬이는 일이 줄어든다.

그러면 이젠 univ객체에 접근하여 professor와 student 정보를 파싱해온다.

String professor = (String)univ.get("professor"); String student = (String)univ.get("student");

저 둘은 " "로 묶인 문자열, 즉 String이기 때문에 (String)을 통해 형변환 하였다. 다시 한번 얘기하지만 JSONObject인 Object형태로 저장된 것이기 때문에 원본에 맞는 타입으로 형변환을 해주어야 한다.

이제 이렇게 나온 결과들이 제대로 된 것이 맞는지 출력을 해보자

System.out.println("교수 : "+professor); System.out.println("학생 : "+student);

잘 출력된다. 코드 전문은 아래와 같다.

코드 구성 : 

import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.json.simple.parser.ParseException; class JSONAdd{ String json; void jsonadd(){ JSONObject inner = new JSONObject(); inner.put("professor", "김교수"); inner.put("student", "이학생"); JSONObject outer = new JSONObject(); outer.put("univ", inner); json = outer.toJSONString(); //System.out.println(json); } } public class Main{ public static void main(String[] args) throws ParseException { JSONAdd jsonAdd = new JSONAdd(); jsonAdd.jsonadd(); JSONParser parser = new JSONParser(); JSONObject obj = (JSONObject)parser.parse(jsonAdd.json); //System.out.println(obj.toJSONString()); JSONObject univ = (JSONObject)obj.get("univ"); //System.out.println(univ.toJSONString()); String professor = (String)univ.get("professor"); String student = (String)univ.get("student"); System.out.println("교수 : "+professor); System.out.println("학생 : "+student); } }

간단하게 정리하면 이렇다.

여기까지 해서 JSON다운로드 방법과 JSON의 구조, 파싱 방법에 대해 알아보았다. 이를 계속 반복하여 익숙하게 하길 바란다. 다음번에는 JSONArray에 대해 알아보도록 하겠다.