如何自定义SpringWebFlux WebClient JSON反序列化?

我正在使用spring-webflux WebClient(build 20170502.221452-172)来访问一个Web应用程序,该应用程序生成一个条目对象流(application/stream+ 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));

虽然 Entry 对象的反序列化对于使用标准通用类型(包括 Java time (JSR-310) 数据类型(如 java.time.Instant))的 POJO 来说效果很好,但我想知道为了将任何自定义 JSON 添加到 Java 反序列化(例如,自定义 Jackson ObjectMapper),我必须做些什么。

我无法在WebClient或其构建器生成的对象类中找到任何API和流畅的API来做到这一点。

有没有人使用WebClient进行自定义的反序列化?

(也许API还不存在?


答案 1

下面是一个自定义 JSON (de)序列化的示例。请注意,出于流式传输目的,使用了不同的编码器/解码器,但其配置的原理保持不变。ObjectMapper

    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();

答案 2

您可以为特定的 Web 客户端配置此内容:

@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));
    };
}

这将通过作为豆子而生效:WebClientAutoConfigurationWebClient.Builder

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