Mar*_*tin 16 java spring json reactive-programming spring-webflux
我正在使用spring-webflux WebClient (build 20170502.221452-172)来访问一个Web应用程序,生成一个Entry对象流(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));
Run Code Online (Sandbox Code Playgroud)
虽然Entry对象的反序列化适用于使用标准公共类型的POJO,包括Java时间(JSR-310)数据类型,如java.time.Instant,但我想知道为了将任何自定义JSON添加到Java反序列化,我必须做什么(例如,自定义Jackson ObjectMapper).
我无法在WebClient或其构建器和流畅API生成的对象的类中找到任何API 来执行此操作.
有没有人使用WebClient进行自定义反序列化?
(也许API不存在,但是?)
Bri*_*zel 19
这是一个自定义ObjectMapperfor JSON(de)序列化的示例.请注意,出于流式传输的目的,正在使用不同的编码器/解码器,但其配置原则保持不变.
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();
Run Code Online (Sandbox Code Playgroud)
Sev*_*One 17
根据上面的回复,我最终得到了这段代码:
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();
Run Code Online (Sandbox Code Playgroud)
如果不包含.findAndRegisterModules(),当您想要反序列化 Java 8 的时间对象等内容时,就会遇到问题。
小智 8
您可以为特定的 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();
}
Run Code Online (Sandbox Code Playgroud)
但也在“应用程序级别”
通过配置一个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));
};
}
Run Code Online (Sandbox Code Playgroud)
这将通过WebClientAutoConfiguration作为WebClient.Builderbean 来实现:
@Autowired
public ItunesAlbumServiceImpl(WebClient.Builder webclientBuilder) {
webClient = webclientBuilder.baseUrl("https://itunes.apple.com").build();
}
Run Code Online (Sandbox Code Playgroud)
全局配置:
@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();
}
}
Run Code Online (Sandbox Code Playgroud)
从 Spring 开始,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();
Run Code Online (Sandbox Code Playgroud)
使用 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()
Run Code Online (Sandbox Code Playgroud)