본문 바로가기

Java

Map과 Json..?

최근 프로젝트를 진행하면서 Json 형태의 데이터를 저장하고 조회해야 하는 일이 생겼다.

( 만약 NoSQL을 사용했다면 더 쉬웠을까? 하지만 사용이 불가능한 상황 =_=;; )

Json 문자열로 변환도 해보고, 객체로 직렬화도 해보고, 여러 가지 시도 끝에 결국 Map이 가장 잘 맞는다고 판단해서 Map을 이용하기로 결정했다.

 

간단한 예제로 설명하자면, persons라는 배열 안에 여러 개의 객체가 있고, 각 객체마다 friends라는 key가 존재한다. 나는 이 friends 값들만 모두 뽑아서 합치고 싶었다.

뭐, persons 배열을 순회하면서 각 객체에서 friends 키의 값을 꺼내고, 이들을 모으면 원하는 결과를 얻을 수 있다. 하지만 더 복잡한 구조의 Json이라면..?!

 

그래서 나는 path 기반 접근 방식을 사용해 friends 값들을 쉽게 추출하는 방법 ( JsonNode의 at() 기능 사용 )을 구현하고자 했다.

persons는 배열이므로 대괄호([])를 이용해 표현했고, 필요하다면 인덱스를 통해 각 요소에 접근할 수도 있다.

 

테스트한 내용은 다음과 같다.

  • Params는 단순한 Map 래퍼이므로 path 기반 접근은 지원하지 않는다.
    • 따라서 persons.get("persons[].friends[]")는 null을 반환해야 한다.
  • jsonMap()으로 변환 후에는 path 기반 접근이 가능해진다.
    • "persons[].friends[]" 경로로 접근한 값은 List 타입이어야 한다.
  • friends 항목은 총 6개가 존재해야 하므로, List의 크기는 6이어야 한다.
  • 명확한 인덱스를 사용하면 특정 요소에 직접 접근 가능해야 한다.
    • persons[1].friends[0] == "muheun"

검증 이후 출력은,,

나는 Json을 최대한 Map처럼 다루고 싶었다. 그래서 Map 기능을 확장한 Params이라는 인터페이스를 만들었고,

( Params를 사용하되 내부적으로 ParamMap을 사용하는지 JsonMap을 사용하는지 사용하는 입장에서는 알 필요가 없다. 기본적으로 ParamMap을 사용하게끔 설계함. )

이를 구현한 ParamMap과 JsonMap 두 가지 클래스를 설계했다. ParamMap은 내부적으로 HashMap을 래핑하고 있으며, 일반 Map보다 약간 더 편하게 사용할 수 있도록 도와준다. 반면 JsonMap은 ObjectNode를 래핑 한 구조로 Json을 Map처럼 다루기 위한 구현체다.

 

( ParamMap은 단순한 Map 래퍼이므로 path 형식 접근은 지원하지 않는다. path 접근이 필요한 경우에는 jsonMap() 메서드를 통해 JsonMap으로 변환해서 사용하면 됨. )

 

참고로 JsonMap 내부 값들은 JsonNode로 변환되기 때문에 일반 Map에 비해 약간의 오버헤드가 존재할 수 있다. 하지만 대용량 데이터를 다루는 게 아니라면 JsonMap을 사용하는 것도 큰 문제는 없어 보인다. -_-y