Wie kann die JSON-Deserialisierung von SpringWebFlux WebClient angepasst werden?
Lesezeit: 3 Minuten
Ich benutze eine spring-webflux WebClient (Build 20170502.221452-172) für den Zugriff auf eine Webanwendung, die einen Stream von Eintrag Objekte (application/stream+json) wie folgt:
Während die Deserialisierung der Eintrag objects funktioniert gut für POJOs, die allgemeine Standardtypen verwenden, einschließlich Java-Zeit (JSR-310)-Datentypen wie java.time.Instant, ich frage mich, was ich tun müsste, um benutzerdefiniertes JSON zur Java-Deserialisierung hinzuzufügen (z. B. einen benutzerdefinierten Jackson ObjectMapper ).
Ich kann darin keine API finden WebClient oder in den Klassen der Objekte, die von seinem Erbauer und fließenden APIs erstellt wurden, um dies zu tun.
Hat jemand WebClient mit angepasster Deserialisierung verwendet?
(Vielleicht ist die API noch nicht da?)
Brian Clozel
Hier ist ein Beispiel, das die anpasst ObjectMapper für die (De-)Serialisierung von JSON. Beachten Sie, dass für Streaming-Zwecke unterschiedliche Encoder/Decoder verwendet werden, das Prinzip für ihre Konfiguration jedoch gleich bleibt.
Können Sie den Grund nennen, warum Jackson2ObjectMapperBuilderCustomizer nicht auf Standard-Codecs angewendet wird?
– Hahn
20. September 2017 um 19:04 Uhr
Das klingt für mich wie eine neue Frage – könnten Sie eine erstellen?
– Brian Clozel
20. September 2017 um 19:12 Uhr
@hahn Wenn Sie anstelle von Webclient.builder() den vorkonfigurierten WebClient.Builder von spring verwenden, können Sie die objectMapper-Anpassungen automatisch vornehmen lassen Ref: docs.spring.io/spring-boot/docs/current/reference/html/…
– Saisurya Kattamuri
26. Mai 2020 um 1:47 Uhr
Sie können dies für einen bestimmten WebClient konfigurieren:
@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();
}
Aber auch auf ‘Anwendungsebene’
durch Konfigurieren von a 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));
};
}
die wirksam gemacht wird durch die WebClientAutoConfiguration Als ein WebClient.Builder Bohne:
@Autowired
public ItunesAlbumServiceImpl(WebClient.Builder webclientBuilder) {
webClient = webclientBuilder.baseUrl("https://itunes.apple.com").build();
}
SchweregradEins
Basierend auf den obigen Antworten habe ich diesen Code erhalten:
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();
Wenn Sie nicht einschließen .findAndRegisterModules()werden Sie Probleme haben, wenn Sie Dinge wie die Zeitobjekte von Java 8 deserialisieren möchten.
Global konfigurieren:
@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();
}
}
Seit Frühjahr 5.1.13 Sie können einen dedizierten verwenden .codec Methode, um sie anzupassen: