기술과 산업/언어 및 프레임워크

Java JSON 처리 실전 시리즈 4화 – JSON을 Java 객체로 역직렬화하기: 날짜, Enum, Optional 대응 전략

B컷개발자 2025. 5. 17. 14:23
728x90

Jackson을 활용해 JSON을 Java 객체로 역직렬화할 때 발생할 수 있는 날짜, Enum, Optional 타입 처리 문제를 실제 예제와 함께 분석하고 해결 방법을 정리합니다.

 


 

1. 역직렬화(Deserialization)란?

 

역직렬화란 JSON 문자열을 Java 객체로 변환하는 과정을 말합니다. Jackson에서는 ObjectMapper.readValue() 메서드로 간단하게 구현할 수 있습니다.

String json = "{\"name\":\"홍길동\", \"age\":30}";
User user = objectMapper.readValue(json, User.class);

하지만 필드 타입이 LocalDateTime, Enum, Optional처럼 단순하지 않을 경우 오류가 발생하기 쉽습니다. 실무에서는 이 세 가지가 가장 많이 문제를 일으킵니다.

 


 

2. 날짜(LocalDate, LocalDateTime) 역직렬화

 

 

문제 상황

{
  "name": "홍길동",
  "joinedAt": "2025-05-09 14:30:00"
}
public class User {
    private String name;
    private LocalDateTime joinedAt;
}

위 코드를 실행하면 다음과 같은 오류가 발생할 수 있습니다:

com.fasterxml.jackson.databind.exc.InvalidFormatException:
Cannot deserialize value of type `java.time.LocalDateTime`

 

해결 방법

 

  1. 전역 설정 (application.yml):
spring:
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
이 방식은 java.util.Date 계열에는 적용되지만, java.time에는 적용되지 않습니다.

 

 

  1. @JsonFormat 사용 (추천)
public class User {
    private String name;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime joinedAt;
}

 


 

3. Enum 타입 역직렬화

 

 

문제 상황

{
  "name": "홍길동",
  "role": "ADMIN"
}
public class User {
    private String name;
    private Role role;

    public enum Role {
        USER, ADMIN
    }
}

이 경우 기본적으로는 문자열로 매핑이 되지만, 다음과 같은 상황에서는 오류가 발생할 수 있습니다:

 

  • JSON에 소문자("admin")로 들어온 경우
  • Enum에 없는 값이 들어오는 경우

 

 

해결 방법

 

  1. Enum 이름을 대소문자 구분 없이 매핑
ObjectMapper mapper = new ObjectMapper();
mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS, true);

 

  1. 예외 처리 추가
@JsonCreator
public static Role from(String value) {
    try {
        return Role.valueOf(value.toUpperCase());
    } catch (Exception e) {
        return Role.USER;
    }
}
위 방식은 잘못된 값이 들어왔을 때 기본값으로 대체하는 전략입니다.

 


 

4. Optional 필드 역직렬화

{
  "name": "홍길동",
  "email": "hong@example.com"
}
public class User {
    private String name;
    private Optional<String> email;
}

 

문제

 

Jackson은 기본적으로 Optional<T>을 처리할 수 있지만, 다음과 같은 조건이 필요합니다:

 

  • Jackson 2.6 이상 사용
  • jackson-datatype-jdk8 의존성 추가 필요
<dependency>
  <groupId>com.fasterxml.jackson.datatype</groupId>
  <artifactId>jackson-datatype-jdk8</artifactId>
</dependency>
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new Jdk8Module());
Spring Boot에서는 자동으로 이 모듈을 등록하지 않으므로 별도 등록이 필요합니다.

 


 

5. Spring Boot에서 역직렬화 오류 무시 설정

 

실무에서 자주 마주하는 문제 중 하나는 정의되지 않은 JSON 필드가 들어오는 경우입니다.

{
  "name": "홍길동",
  "age": 30,
  "unknownField": "unexpected"
}
public class User {
    private String name;
    private int age;
}

이럴 경우 기본 설정에서는 UnrecognizedPropertyException이 발생합니다.

 

 

해결 방법

spring:
  jackson:
    deserialization:
      fail-on-unknown-properties: false

혹은 Java 설정:

mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

 


 

결론 및 요약

문제 유형해결 방법

LocalDateTime 오류 @JsonFormat 패턴 지정
Enum 대소문자 이슈 MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS 사용
Optional 처리 jackson-datatype-jdk8 모듈 등록 필요
알 수 없는 필드 오류 FAIL_ON_UNKNOWN_PROPERTIES 비활성화

 


 

다음 회차 예고

 

5화에서는 JSON 필드명을 자동으로 Camel ↔ Snake Case로 변환하는 전략을 다룹니다. @JsonNaming, 글로벌 설정, yml 기반 설정을 통해 코드와 JSON의 명확한 분리를 어떻게 할 수 있는지 실전 예제와 함께 소개합니다.

728x90