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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/43769301/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 07:42:35  来源:igfitidea点击:

How to customize SpringWebFlux WebClient JSON deserialization?

javajsonspringreactive-programmingspring-webflux

提问by Martin

I'm using a spring-webflux WebClient(build 20170502.221452-172) to access a Web application producing a stream of Entryobjects (application/stream+json) like this:

我正在使用spring-webflux WebClient(构建 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));

While the deserialization of the Entryobjects works fine for POJOs using standard common types including Java time (JSR-310) datatypes like java.time.Instant, I wonder what I would have to do in order to add any custom JSON to Java deserialization (e. g., a custom Hymanson ObjectMapper).

虽然Entry对象的反序列化适用于使用标准通用类型(包括 Java 时间(JSR-310)数据类型(如 java.time.Instant))的 POJO,但我想知道我必须做什么才能将任何自定义 JSON 添加到 Java 反序列化(例如,自定义 Hymanson ObjectMapper)。

I can't find any API in WebClientor in the classes of the objects produced by its builder and fluent APIs to do that.

我在WebClient或其构建器和流畅的 API 生成的对象的类中找不到任何 API来执行此操作。

Has anybody used WebClient with customized deserialization?

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

(Maybe the API is not there, yet?)

(也许 API 还不存在?)

回答by Brian Clozel

Here's an example that customizes the ObjectMapperfor JSON (de)serialization. Note that for streaming purposes, different encoders/decoders are being used but the principle remains the same for their configuration.

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

    ExchangeStrategies strategies = ExchangeStrategies
            .builder()
            .codecs(clientDefaultCodecsConfigurer -> {
                clientDefaultCodecsConfigurer.defaultCodecs().Hymanson2JsonEncoder(new Hymanson2JsonEncoder(new ObjectMapper(), MediaType.APPLICATION_JSON));
                clientDefaultCodecsConfigurer.defaultCodecs().Hymanson2JsonDecoder(new Hymanson2JsonDecoder(new ObjectMapper(), MediaType.APPLICATION_JSON));

            }).build();

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

回答by Ricardo

You can configure this for a specific WebClient:

您可以为特定的 WebClient 配置它:

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

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

But also on 'application level'

但也在“应用程序级别”

by configuring a CodecCustomizer:

通过配置一个CodecCustomizer

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

which will be made effective by the WebClientAutoConfigurationas a WebClient.Builderbean:

这将通过WebClientAutoConfiguration作为WebClient.Builderbean 来实现:

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

回答by Amit Yatagiri

with webflux 5.0.2, de-registerDefaults

使用 webflux 5.0.2,取消注册默认值

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

回答by Sarvar Nishonboev

Configuring globally:

全局配置:

@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() {
        Hymanson2JsonEncoder encoder = new Hymanson2JsonEncoder(objectMapper);
        Hymanson2JsonDecoder decoder = new Hymanson2JsonDecoder(objectMapper);
        return ExchangeStrategies
                .builder()
                .codecs(configurer -> {
                    configurer.defaultCodecs().Hymanson2JsonEncoder(encoder);
                    configurer.defaultCodecs().Hymanson2JsonDecoder(decoder);
                }).build();
    }
}

回答by tomasulo

Since Spring 5.1.13you can use a dedicated .codecmethod to customize them:

从 Spring 开始,5.1.13您可以使用专用.codec方法来自定义它们:

WebClient.builder()
    .codecs(configurer -> {
        configurer.defaultCodecs().Hymanson2JsonEncoder(new Hymanson2JsonEncoder(new ObjectMapper(), MediaType.APPLICATION_JSON));
        configurer.defaultCodecs().Hymanson2JsonDecoder(new Hymanson2JsonDecoder(new ObjectMapper(), MediaType.APPLICATION_JSON));
     })
    .build();