형식을 알지 못하는 JSON을 클래스로 만들 수 있을까?
먼저 도대체 형식을 알지 못하는 JSON을 파싱해야하는 경우가 어떤 경우인지 알아보자.
여러 가지를 정할 수 있는 음식주문 서비스를 생각해보자. 가게마다 가능한 옵션이 다를 것이다. 중국집에는 짜장면 : [오이x, 양파x, 파x, 고기x]. 분식집에서는 라면 : [계란o, 파o, 양파o, 고기o] 와 같은 옵션이 가능할 것이다.
이것을 DB에 어떻게 저장할 수 있을까? 컬럼에는 저장이 불가능하다고 판단했고..무한 컬럼을 사용할 수는 없으니까...DB에 JSON 형식을 사용해서 저장하기로 했다. 그리고 클라이언트가 json을 알아서 파싱해서 사용하기로 했다.
json <-> object 변환에 대해서는 여러 라이브러리가 있고 자료도 많다. 하지만 이 상황은 전부 JSON응답 형식을 알고 있을 때 변환하는 상황이다. 하지만 내가 처한 상황은 응답 JSON의 형식이 너무 가변적이어서 파싱할 클래스를 만들 수 없다. 그래서 응답을 받고 json형식에 맞춰 클래스를 생성하고 파싱하는 방법은 없을지 생각해 봤다. 결론부터 말하면 내 짧은 식견으로는 아마 불가능한것 같다. (사실 SW세계에서 불가능한 것은 없다라고 생각하지만 내 짧은 지식 안에서는 내가 지금 만들거나 사용할 수 없다고 판단했다.)
먼저 json형태를 읽어서 클래스를 생성해야한다. 이는 java코드를 생성한다는 말인데 이미 컴파일이 완료 되어서 돌아가고 있는 자바 프로그램에 java코드를 생성해서 중간에 덧붙여 동작하게 한다는 것은 안된다. 아래의 java 실행과정을 보자. .java -> .class -> load, linking, initialization의 과정을 거친다. 그리고 JVM에서 추가적인 과정을 거친다. 아래의 과정을 완벽하게 이해하고 수정가능하다면 중간에 java코드를 생성. 실행중인 프로그램에 덧붙일 수 있을지도 모르겠다.. 일단 내가 지금 할 수 있는 일은 아니다.
그럼 이 문제를 어떻게 해결했나? 사실 내 프로젝트에서는 서버가 단순 JSON의 저장소 역할만 하고 다른 처리를 하지 않았다. 처리를 필요로 하는 기능이 없었기 때문이다. 단순 저장했다가 클라이언트에게 다시 뿌려주면 된다. 사용하는 것은 클라이언트에서 알아서 사용...
하지만 만약 객체로 파싱해야한다면 어떻게 할 수 있을까? 그리고 클라이언트는 결과를 알 수 없는 json을 파싱해야하는데 어떻게 사용할 수 있을까?
-> Map을 사용할 수 있다. Map은 객체의 추상화, 일반화라고 생각해도 된다. key는 멤버변수의 이름, value는 멤버 변수의 값으로 생각하면 어떤 객체이든 Map으로 변환할 수 있고 어떤 Map도 객체로 변환할 수 있다는게 이해될 것이다.(Map<Object, Object> 또는 Map<String, Object>를 생각하면 된다.) 즉, 어떤 JSON이든 Map으로는 파싱 가능하다는 것이다.
그리고 Map의 좋은 점은 멤버 변수의 이름을 알아야 접근 가능한 일반 클래스와 달리 map.ketSet()으로 존재하는 멤버의 이름을 모두 조회하고 접근할 수 있다는 것이다. Map은 정말 똑똑하게 설계된 놈이다. Map을 애용하도록 해야겠다.