ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Java JSON 처리 실전 시리즈 4화 – JSON을 Java 객체로 역직렬화하기: 날짜, Enum, Optional 대응 전략
    기술과 산업/언어 및 프레임워크 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
Designed by Tistory.