programing

Spring WebFlux WebClient JSON 역직렬화 커스터마이즈 방법

randomtip 2023. 4. 1. 15:10
반응형

Spring WebFlux WebClient JSON 역직렬화 커스터마이즈 방법

spring-webflux WebClient(빌드 20170502.221452-172)를 사용하여 다음과 같은 Entry 개체(애플리케이션/스트림+json) 스트림을 생성하는 웹 애플리케이션에 액세스하고 있습니다.

final WebClient producerClient = WebClient.create("http://localhost:8080/");

Flux<Entry> entries = producerClient.get().uri("json-stream")
        .accept(MediaType.APPLICATION_STREAM_JSON)
        .exchange()
        .flatMapMany(clientResponse -> clientResponse.bodyToFlux(Entry.class));

엔트리 오브젝트의 역직렬화는 Java time(JSR-310) 등의 데이터 타입을 포함한 표준 공통 타입을 사용하는 POJO에서는 정상적으로 동작합니다.즉, Java 역직렬화에 커스텀 JSON을 추가하려면 어떻게 해야 할까(예: 커스텀 Jackson Object Mapper) 궁금해집니다.

WebClient나 빌더에 의해 생성된 오브젝트 클래스에서 API를 찾을 수 없으며 이를 위한 유창한 API도 찾을 수 없습니다.

맞춤형 역직렬화와 함께 Web Client를 사용한 적이 있습니까?

(API가 아직 없는 것 같습니까?)

다음 예시는 다음 예시를 통해ObjectMapperJSON(디시리얼라이제이션)의 경우.스트리밍을 목적으로 다른 인코더/디코더가 사용되고 있지만, 그 설정에서는 원칙은 변하지 않는 것에 주의해 주세요.

    ExchangeStrategies strategies = ExchangeStrategies
            .builder()
            .codecs(clientDefaultCodecsConfigurer -> {
                clientDefaultCodecsConfigurer.defaultCodecs().jackson2JsonEncoder(new Jackson2JsonEncoder(new ObjectMapper(), MediaType.APPLICATION_JSON));
                clientDefaultCodecsConfigurer.defaultCodecs().jackson2JsonDecoder(new Jackson2JsonDecoder(new ObjectMapper(), MediaType.APPLICATION_JSON));

            }).build();

    WebClient webClient = WebClient.builder().exchangeStrategies(strategies).build();

특정 WebClient에 대해 다음과 같이 설정할 수 있습니다.

@Autowired
public ItunesAlbumServiceImpl(ObjectMapper mapper) {
    ExchangeStrategies strategies = ExchangeStrategies.builder().codecs(clientCodecConfigurer ->
        clientCodecConfigurer.customCodecs().decoder(
                new Jackson2JsonDecoder(mapper,
                        new MimeType("text", "javascript", StandardCharsets.UTF_8)))
    ).build();

    webClient = WebClient.builder()
            .exchangeStrategies(strategies)
            .baseUrl("https://itunes.apple.com")
            .build();
}

또, 「어플리케이션 레벨」에서도

를 설정함으로써CodecCustomizer:

@Bean
public CodecCustomizer jacksonLegacyJsonCustomizer(ObjectMapper mapper) {
    return (configurer) -> {
        MimeType textJavascript = new MimeType("text", "javascript", StandardCharsets.UTF_8);
        CodecConfigurer.CustomCodecs customCodecs = configurer.customCodecs();
        customCodecs.decoder(
                new Jackson2JsonDecoder(mapper, textJavascript));
        customCodecs.encoder(
                new Jackson2JsonEncoder(mapper, textJavascript));
    };
}

이 기능은, 에 의해서 유효하게 됩니다.WebClientAutoConfiguration로서WebClient.Builder콩:

@Autowired
public ItunesAlbumServiceImpl(WebClient.Builder webclientBuilder) {
    webClient = webclientBuilder.baseUrl("https://itunes.apple.com").build();
}

위의 답변에 근거해, 저는 다음과 같은 코드로 종료했습니다.

final ObjectMapper mapper = new ObjectMapper()
    .findAndRegisterModules()
    .enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
final ExchangeStrategies exchangeStrategies = ExchangeStrategies.builder()
    .codecs(configurer -> configurer.defaultCodecs()
    .jackson2JsonDecoder(new Jackson2JsonDecoder(mapper)))
    .build();
final WebClient webClient = WebClient.builder()
    .exchangeStrategies(exchangeStrategies)
    .build();

포함하지 않는 경우.findAndRegisterModules()Java 8의 시간 개체와 같은 것을 역직렬화하려는 경우 문제가 발생합니다.

글로벌하게 설정:

@Configuration
public class AppConfig {

    private final ObjectMapper objectMapper;

    @Autowired
    public AppConfig(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
        this.webClientBuilder = WebClient.builder()
                .exchangeStrategies(exchangeStrategies());
    }

    private ExchangeStrategies exchangeStrategies() {
        Jackson2JsonEncoder encoder = new Jackson2JsonEncoder(objectMapper);
        Jackson2JsonDecoder decoder = new Jackson2JsonDecoder(objectMapper);
        return ExchangeStrategies
                .builder()
                .codecs(configurer -> {
                    configurer.defaultCodecs().jackson2JsonEncoder(encoder);
                    configurer.defaultCodecs().jackson2JsonDecoder(decoder);
                }).build();
    }
}

봄부터5.1.13전용을 사용할 수 있습니다..codec커스터마이즈 방법:

WebClient.builder()
    .codecs(configurer -> {
        configurer.defaultCodecs().jackson2JsonEncoder(new Jackson2JsonEncoder(new ObjectMapper(), MediaType.APPLICATION_JSON));
        configurer.defaultCodecs().jackson2JsonDecoder(new Jackson2JsonDecoder(new ObjectMapper(), MediaType.APPLICATION_JSON));
     })
    .build();

webflux 5.0.2, 디폴트 등록 해제

val strategies = ExchangeStrategies.builder()
                .codecs { configurer ->
                    configurer.registerDefaults(false)
                    configurer.customCodecs().encoder(Jackson2JsonEncoder(objectMapper, APPLICATION_JSON))
                    configurer.customCodecs().decoder(Jackson2JsonDecoder(objectMapper, APPLICATION_JSON))
                }.build()

언급URL : https://stackoverflow.com/questions/43769301/how-to-customize-springwebflux-webclient-json-deserialization

반응형