ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Jackson JSON 트러블슈팅을 위한 각 오류별 구체적인 예제와 JUnit 기반 테스트 코드
    기술과 산업/언어 및 프레임워크 2025. 5. 19. 11:07
    728x90

    Jackson JSON 트러블슈팅을 위한 각 오류별 구체적인 예제와 JUnit 기반 테스트 코드를 정리한 Java 코드 문서를 생성했습니다. 이 문서에는 다음과 같은 내용을 포함하고 있습니다:

    • UnrecognizedPropertyException (정의되지 않은 필드)
    • InvalidFormatException (타입 불일치)
    • JavaTimeModule 미등록으로 인한 날짜 오류
    • Enum 역직렬화 실패
    • 순환 참조 문제와 @JsonManagedReference, @JsonBackReference 사용 예제
    // Java JSON 처리 실전 – Jackson 트러블슈팅 확장 예제 모음
    
    // 1. UnrecognizedPropertyException 예제
    
    public class User {
        private String name;
        private int age;
        // getter, setter
    }
    
    @Test
    void testUnrecognizedField() throws Exception {
        String json = "{\"name\":\"홍길동\", \"age\":30, \"unknown\":\"test\"}";
        ObjectMapper mapper = new ObjectMapper();
        Assertions.assertThrows(UnrecognizedPropertyException.class, () -> {
            mapper.readValue(json, User.class);
        });
    }
    
    // 해결: 무시 설정 추가
    @JsonIgnoreProperties(ignoreUnknown = true)
    public class UserSafe {
        private String name;
        private int age;
    }
    
    // 2. InvalidFormatException 예제
    
    public class AgeUser {
        private int age;
    }
    
    @Test
    void testInvalidFormat() throws Exception {
        String json = "{\"age\":\"abc\"}";
        ObjectMapper mapper = new ObjectMapper();
        Assertions.assertThrows(InvalidFormatException.class, () -> {
            mapper.readValue(json, AgeUser.class);
        });
    }
    
    // 3. JavaTimeModule 미등록 예제
    
    public class DateUser {
        private LocalDateTime createdAt;
    }
    
    @Test
    void testMissingJavaTimeModule() throws Exception {
        String json = "{\"createdAt\":\"2025-05-10T15:00:00\"}";
        ObjectMapper mapper = new ObjectMapper();
        Assertions.assertThrows(InvalidDefinitionException.class, () -> {
            mapper.readValue(json, DateUser.class);
        });
    }
    
    // 해결: 모듈 등록
    @Test
    void testWithJavaTimeModule() throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new JavaTimeModule());
        String json = "{\"createdAt\":\"2025-05-10T15:00:00\"}";
        DateUser user = mapper.readValue(json, DateUser.class);
        Assertions.assertNotNull(user.getCreatedAt());
    }
    
    // 4. Enum 역직렬화 오류 및 해결
    
    public enum Role {
        ADMIN, USER
    }
    
    public class RoleUser {
        private Role role;
    }
    
    @Test
    void testEnumFail() throws Exception {
        String json = "{\"role\":\"admin\"}";
        ObjectMapper mapper = new ObjectMapper();
        Assertions.assertThrows(IllegalArgumentException.class, () -> {
            mapper.readValue(json, RoleUser.class);
        });
    }
    
    // 해결: 대소문자 무시
    @Test
    void testEnumSuccessWithInsensitive() throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS, true);
        String json = "{\"role\":\"admin\"}";
        RoleUser user = mapper.readValue(json, RoleUser.class);
        Assertions.assertEquals(Role.ADMIN, user.getRole());
    }
    
    // 5. 순환 참조 문제 해결
    
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    class Parent {
        public String name;
    
        @JsonManagedReference
        public Child child;
    }
    
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    class Child {
        public String name;
    
        @JsonBackReference
        public Parent parent;
    }
    
    @Test
    void testCyclicReference() throws Exception {
        Parent parent = new Parent("부모", null);
        Child child = new Child("자식", parent);
        parent.setChild(child);
    
        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString(parent);
        Assertions.assertTrue(json.contains("부모"));
        Assertions.assertTrue(json.contains("자식"));
        Assertions.assertFalse(json.contains("parent")); // 역참조 제외됨
    }

     

    Spring Boot 통합 테스트 형식 주요 특징은 다음과 같습니다:

    • @SpringBootTest, @AutoConfigureMockMvc를 사용한 테스트 환경 구성
    • MockMvc를 통한 실제 HTTP 요청 시뮬레이션
    • /user 엔드포인트: 정의되지 않은 필드(UnrecognizedPropertyException) 테스트
    • /role 엔드포인트: 대소문자 민감한 Enum 역직렬화 오류와 그 해결 테스트
    • Jackson2ObjectMapperBuilderCustomizer를 활용한 설정 커스터마이징 예제 포함
    // Jackson 트러블슈팅 – Spring Boot 통합 테스트 기반 예제
    
    @SpringBootTest
    @AutoConfigureMockMvc
    public class JacksonErrorIntegrationTest {
    
        @Autowired
        private MockMvc mockMvc;
    
        @RestController
        static class TestController {
    
            @PostMapping("/user")
            public ResponseEntity<String> createUser(@RequestBody User user) {
                return ResponseEntity.ok("OK");
            }
    
            @PostMapping("/role")
            public ResponseEntity<String> assignRole(@RequestBody RoleUser roleUser) {
                return ResponseEntity.ok("OK");
            }
        }
    
        static class User {
            public String name;
            public int age;
        }
    
        static class RoleUser {
            public Role role;
        }
    
        enum Role {
            ADMIN, USER
        }
    
        @Test
        void unrecognizedFieldReturns400() throws Exception {
            String invalidJson = "{\"name\":\"홍길동\", \"age\":30, \"unknown\":\"???\"}";
    
            mockMvc.perform(post("/user")
                    .contentType(MediaType.APPLICATION_JSON)
                    .content(invalidJson))
                .andExpect(status().isBadRequest());
        }
    
        @Test
        void invalidEnumValueReturns400() throws Exception {
            String json = "{\"role\":\"admin\"}";
    
            mockMvc.perform(post("/role")
                    .contentType(MediaType.APPLICATION_JSON)
                    .content(json))
                .andExpect(status().isBadRequest());
        }
    
        @TestConfiguration
        static class CustomConfig {
            @Bean
            public Jackson2ObjectMapperBuilderCustomizer customizer() {
                return builder -> builder.featuresToEnable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS);
            }
        }
    
        @Test
        void validEnumWithInsensitiveEnabled() throws Exception {
            String json = "{\"role\":\"admin\"}";
    
            mockMvc.perform(post("/role")
                    .contentType(MediaType.APPLICATION_JSON)
                    .content(json))
                .andExpect(status().isOk());
        }
    }

     

    이제 이 코드를 실제 Spring Boot 프로젝트의 통합 테스트로 실행할 수 있으며, 실무 현장에서 JSON 처리 트러블슈팅을 자동화 테스트로 검증하는 데 활용하실 수 있습니다.

    728x90
Designed by Tistory.