Post

(Java) Jackson 프로퍼티명 snake\_case <-> camelCase 변환

Jackson ObjectMapper 변환

https://stackoverflow.com/questions/10519265/jackson-overcoming-underscores-in-favor-of-camel-case

A.@

JsonProperty 애너테이션으로 각 필드에 명시해주는 방법

B. 각각의 data class에서@JsonNaming 애너테이션으로 어떤 이름 변환 사용할지 명시해 주는 방법
1
@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
C. 아예 ObjectMapper 자체에 기본 property-naming-strategy를 설정해주는 방법

C-1 참조

비교
  • 자유도는 A가 가장 높고 C가 가장 낮다.
  • 자유도가 가장 낮은 C로 가게 되면 여러가지 번거로운 설정이 들어가야 하는 경우가 있어서 좀 귀찮고, 이렇게 전역적인 객체를 사용해서 처리하는 방법은 결국 유연성이 떨어져 나중에 수용하지 못하는 케이스가 생기게 된다. (C -> B -> A 로 결국 바꾸어야 하는 순간이 온다는 것)
    • 중복 같아 보여도 처음부터 B부터 고려하는 편이 낫다.
  • 보통 B를 택하고, B로 수용이 안되는 경우 A를 택하는 것을 추천.
    • A를 써야 하는 case?
      • 프로퍼티명이 줄임말이라 내부 컨벤션 대로 바꿔주어야 하는 경우
      • snake_case 변환이 제대로 먹히지 않는 형태인 경우 (간혹 있음)
      • 한 응답 json 안에 snake_case와 camelCase가 둘 다 있는 경우
      • 추상화 시 서로 다른 클래스들의 필드명을 동일하게 맞춰주어야 하는 경우

C-1. SpringBoot에서 SNAKE_CASE 등의 처리를 추가한 ObjectMapper를 사용하고 싶다면?

C에서, SpringBoot 같은 경우 JacksonAutoConfiguration이 동작하면서 이미 ObjectMapper Bean이 만들어지도록 되어 있다. 그러나 SNAKE_CASE 등의 처리를 추가한 ObjectMapper를 사용하고 싶다면?

  1. application.properties 설정을 사용해서, JacksonAutoConfiguration 에서 기본 ObjectMapper 빈 생성할 때 설정을 포함하여 생성할 수 있도록 하는 방법

    • spring.jackson.property-naming-strategy=SNAKE_CASE 설정인데…
    • 문제는 이렇게 기본으로 만들어버리면,

    이미 camelCase로 되어 있는 API 응답을 받을 때도 적용되어 버려서 응답 json에 camel_case인 필드가 없는데요? 라고 에러를 내버린다!

    • 그래서 이 설정을 기본으로 일괄 적용하는 것은 좋지 않아 보인다.
  2. 자체적으로 ObjectMapper 정의한 다음, @Bean 으로 만드는 방법.
    • JacksonAutoConfiguration.JacksonObjectMapperConfiguration.jacksonObjectMapper에서 @ConditionalOnMissingBean등으로 이미 정의된 ObjectMapper 타입의 Bean이 있는지 체크 한 다음 빈으로 만들기 때문에, ObjectMapper Bean이 따로 2개가 생성되는게 아니다.
  3. (kotlin) 최상위에 MY_OBJECT_MAPPER를 정의하고 Bean으로 만들지 않고 쓰는 방법.

WebClient 적용

  • Spring Default ObjectMapper 말고 다른 ObjectMapper 사용하기
  • SNAKE_CASE 변환 등 다른 기능이 필요한 경우
1
2
3
4
5
6
7
8
9
10
private val webClient = webClientBuilder
.codecs {
it.defaultCodecs().jackson2JsonEncoder(Jackson2JsonEncoder(SNAKE\_CASE\_OBJECT\_MAPPER))
it.defaultCodecs().jackson2JsonDecoder(Jackson2JsonDecoder(SNAKE\_CASE\_OBJECT\_MAPPER))
}
.build()


.exchangeStrategies(SNAKE\_CASE\_EXCHANGE\_STRATEGIES)
// codes 말고 이렇게도 설정 가능한데 왜 인지 이 방법은 안되고, docs에서도 codecs를 사용하는 방법을 권장하고 있음
This post is licensed under CC BY 4.0 by the author.