본문으로 건너뛰기
Advertisement

3.7 ObjectMapper를 이용한 수동 JSON 처리

스프링 부트는 컨트롤러에서 @RequestBody@ResponseBody를 통해 JSON 처리를 자동화해주지만, 실무에서는 외부 API 연동이나 복잡한 로직 처리를 위해 자바 코드에서 직접 JSON을 파싱해야 할 때가 많습니다. 이때 사용하는 것이 Jackson 라이브러리의 핵심 객체인 ObjectMapper 입니다.

1. 기본 사용법

객체를 JSON 문자열로 변환 (Serialization)

자바 객체를 JSON 형태의 문자열로 만드는 과정을 직렬화라고 합니다.

ObjectMapper mapper = new ObjectMapper();
User user = new User("hong", 20);

// 객체 -> JSON 문자열
String json = mapper.writeValueAsString(user);
// 결과: {"name":"hong","age":20}

JSON 문자열을 객체로 변환 (Deserialization)

반대로 JSON 문자열을 읽어 자바 객체로 만드는 과정을 역직렬화라고 합니다.

String json = "{\"name\":\"hong\",\"age\":20}";

// JSON 문자열 -> 객체
User user = mapper.readValue(json, User.class);

2. 컬렉션 처리 (List, Map)

단일 객체뿐만 아니라 리스트나 맵 형태도 쉽게 다룰 수 있습니다.

List 처리

String jsonList = "[{\"name\":\"hong\"}, {\"name\":\"kim\"}]";
List<User> list = mapper.readValue(jsonList, new TypeReference<List<User>>() {});

Map 처리

String json = "{\"name\":\"hong\", \"age\":20}";
Map<String, Object> map = mapper.readValue(json, new TypeReference<Map<String, Object>>() {});

3. ObjectMapper 주요 설정 옵션

ObjectMapper를 생성할 때 다양한 설정을 통해 동작을 변경할 수 있습니다.

역직렬화 설정 (DeserializationFeature)

  • FAIL_ON_UNKNOWN_PROPERTIES (기본값: true):
    • JSON에는 필드가 있는데 자바 클래스에는 없을 경우 에러를 낼지 결정합니다.
    • 실무에서는 API 스펙 변경에 유연하게 대처하기 위해 보통 false로 설정합니다.
    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

직렬화 설정 (SerializationFeature)

  • WRITE_DATES_AS_TIMESTAMPS (기본값: true):
    • 날짜 객체를 타임스탬프(숫자)로 보낼지, ISO-8601 문자열로 보낼지 결정합니다.
    mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); // 문자열로 출력

포함 정책 (JsonInclude)

  • Include.NON_NULL:
    • 필드 값이 null인 경우 JSON 결과에서 아예 제외합니다.
    mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

4. 클래스 레벨 애너테이션 활용

클래스 필드에 직접 선언하여 개별적으로 제어할 수도 있습니다.

  • @JsonProperty("custom_name"): JSON의 키 이름을 자바 필드명과 다르게 지정할 때 사용합니다.
  • @JsonIgnore: 특정 필드를 JSON 변환에서 제외합니다. (예: 비밀번호)
  • @JsonFormat: 날짜 형식을 지정합니다.
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createdAt;

5. 스프링 부트에서 ObjectMapper 주입받기

스프링 부트는 이미 최적화된 ObjectMapper를 빈(Bean)으로 등록해 두었습니다. 새로운 객체를 new로 생성하기보다는 의존성 주입(DI)을 통해 사용하는 것이 좋습니다.

@Service
@RequiredArgsConstructor
public class MyService {
private final ObjectMapper objectMapper; // 스프링이 관리하는 빈 주입

public void process(String json) throws JsonProcessingException {
User user = objectMapper.readValue(json, User.class);
// ...
}
}
경고

ObjectMapper는 생성 비용이 비싸지만 멀티스레드 환경에서 안전(Thread-safe)하므로, 매번 new로 생성하지 않고 하나의 인스턴스를 공유하거나 스프링 빈을 주입받아 사용 하는 것이 성능상 유리합니다.

Advertisement