web-dev-qa-db-fra.com

Comment personnaliser la désérialisation JSON de SpringWebFlux WebClient?

J'utilise un spring-webflux WebClient (build 20170502.221452-172) pour accéder à une application Web produisant un flux de Entrée objets (application/stream + json) comme celui-ci:

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

Bien que la désérialisation des objets Entry fonctionne correctement pour les POJO utilisant des types communs standard, y compris les types de données Java Time (JSR-310) tels que Java.time.Instant, je me demande ce que je devrais faire pour en ajouter. désérialisation JSON vers Java personnalisé (par exemple, un ObjectMapper Jackson personnalisé).

Je ne trouve aucune API dans WebClient ou dans les classes des objets générés par ses API constructeur et fluent pour le faire.

Quelqu'un at-il utilisé WebClient avec une désérialisation personnalisée?

(Peut-être que l'API n'est pas encore là?)

10
Martin

Voici un exemple qui personnalise la ObjectMapper pour la (dé) sérialisation JSON. Notez que pour la diffusion en continu, différents encodeurs/décodeurs sont utilisés, mais le principe reste le même pour leur configuration.

    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();
11
Brian Clozel

Vous pouvez configurer ceci pour un WebClient spécifique:

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

Mais aussi au niveau de l'application

en configurant une 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));
    };
}

qui sera rendu effectif par le WebClientAutoConfiguration sous la forme d'un bean WebClient.Builder:

@Autowired
public ItunesAlbumServiceImpl(WebClient.Builder webclientBuilder) {
    webClient = webclientBuilder.baseUrl("https://iTunes.Apple.com").build();
}
1
Ricardo

avec webflux 5.0.2, annulez les registres `` `

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

`` `

0
Amit Yatagiri