programing

구성된 ObjectMapper가 spring-boot-webflux에서 사용되지 않음

projobs 2023. 6. 23. 23:36
반응형

구성된 ObjectMapper가 spring-boot-webflux에서 사용되지 않음

나는 일반 스프링 웹 컨트롤러를 사용하여 객체 맵빌더 구성에 믹스인에 따라 출력되는 데이터를 구성했습니다.그러나 webflux를 사용하여 Flow 또는 Mono를 반환하는 메서드가 있는 컨트롤러는 객체가 기본 데이터를 매핑하는 것처럼 데이터를 직렬화합니다.

webflux를 사용하여 개체 매퍼 구성을 강제로 적용하는 방법은 무엇입니까?

샘플 구성:

@Bean
JavaTimeModule javatimeModule(){
    return new JavaTimeModule();
}

@Bean
Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer(){
return jacksonObjectMapperBuilder ->  jacksonObjectMapperBuilder.featuresToEnable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
                                                                    .mixIn(MyClass.class, MyClassMixin.class);
}

실제로 init 코드를 통해 해결책을 찾았습니다.

@Configuration
public class Config {

    @Bean
    JavaTimeModule javatimeModule(){
        return new JavaTimeModule();
    }

    @Bean
    Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer(){
    return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.featuresToEnable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
            .mixIn(MyClass.class, MyClassMixin.class);
    }


    @Bean
    Jackson2JsonEncoder jackson2JsonEncoder(ObjectMapper mapper){
       return new Jackson2JsonEncoder(mapper);
    }

    @Bean
    Jackson2JsonDecoder jackson2JsonDecoder(ObjectMapper mapper){
        return new Jackson2JsonDecoder(mapper);
    }

    @Bean
    WebFluxConfigurer webFluxConfigurer(Jackson2JsonEncoder encoder, Jackson2JsonDecoder decoder){
        return new WebFluxConfigurer() {
            @Override
            public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
                configurer.defaultCodecs().jackson2JsonEncoder(encoder);
                configurer.defaultCodecs().jackson2JsonDecoder(decoder);
            }
        };

    }
}

나는 @Alberto Galiana의 솔루션을 Java로 변환하고 구성된 Objectmapper를 편리하게 주입했기 때문에 여러 구성을 수행할 필요가 없습니다.

@Configuration
@RequiredArgsConstructor
public class WebFluxConfig implements WebFluxConfigurer {

    private final ObjectMapper objectMapper;

    public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
        configurer.defaultCodecs().jackson2JsonEncoder(
            new Jackson2JsonEncoder(objectMapper)
        );

        configurer.defaultCodecs().jackson2JsonDecoder(
            new Jackson2JsonDecoder(objectMapper)
        );
    }
}

WebFluxConfigurer를 구현하고 메서드 configureHttpMessageCodecs를 재정의하기만 하면 됩니다.

Spring Boot 2 + Kotlin 샘플 코드

@Configuration
@EnableWebFlux
class WebConfiguration : WebFluxConfigurer {

    override fun configureHttpMessageCodecs(configurer: ServerCodecConfigurer) {
        configurer.defaultCodecs().jackson2JsonEncoder(Jackson2JsonEncoder(ObjectMapper()
                .setSerializationInclusion(JsonInclude.Include.NON_EMPTY)))

        configurer.defaultCodecs().jackson2JsonDecoder(Jackson2JsonDecoder(ObjectMapper()
                .enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)))
    }
}

속성 이름이 클래스와 json 데이터에서 동일하더라도 인코딩/디코드할 모든 데이터 클래스에 모든 속성에 @JsonProperty로 주석을 달아야 합니다.

data class MyClass(
    @NotNull
    @JsonProperty("id")
    val id: String,

    @NotNull
    @JsonProperty("my_name")
    val name: String)

저의 경우, 저는 사용하려고 했습니다.ObjectMapper내 앱의 기본값에서 모든 동작을 상속하는 동안WebClient.

사용해야 한다는 것을 알게 되었습니다.WebClient.Builder.codecs사용한 경우WebClient.Builder.exchangeStrategies제공된 재정의가 무시되었습니다.이 동작이 사용과 관련된 것인지 확실하지 않습니다.WebClient.mutate하지만 이게 유일한 해결책입니다

WebClient customizedWebClient = webClient.mutate()
                                         .codecs(clientCodecConfigurer -> 
                                                     clientCodecConfigurer.defaultCodecs()
                                                                          .jackson2JsonDecoder(new Jackson2JsonDecoder(customObjectMapper)))
                                         .build();

저는 모든 다양한 해결책을 시도해 보았습니다.@Primary @Bean위해서ObjectMapper,configureHttpMessageCodecs()등).마지막에 저에게 효과가 있었던 것은 MIME 유형을 지정하는 것이었습니다.다음은 예입니다.

@Configuration
class WebConfig: WebFluxConfigurer {
override fun configureHttpMessageCodecs(configurer: ServerCodecConfigurer) {
        val encoder = Jackson2JsonEncoder(objectMapper, MimeTypeUtils.APPLICATION_JSON)
        val decoder = Jackson2JsonDecoder(objectMapper, MimeTypeUtils.APPLICATION_JSON)
        configurer.defaultCodecs().jackson2JsonEncoder(encoder)
        configurer.defaultCodecs().jackson2JsonDecoder(decoder)
    }
}

언급URL : https://stackoverflow.com/questions/43195987/configured-objectmapper-not-used-in-spring-boot-webflux

반응형