java - WebFlux 主体序列化为依赖于运行时的模型?
问题描述
当有一个ClientResponse
来自 WebClient 的时候,在最简单的情况下我们使用
clientResponse.bodyToMono(MyResponseModel.class)
来序列化响应体。
但目前尚不清楚当响应格式因情况而异时该怎么办。
例如,当响应可能是两种类型之一时
type 1: {"a": <number>, "b": <string>}
type 2: {"c": <date>, "d": {"items": <array>}}
我想基本算法应该是这样的
- 尝试序列化为类型 1
- 如果确定返回类型 1 的模型
- 否则尝试序列化为类型 2
- 如果确定返回类型 2 的模型
- else 序列化错误
使用 Spring WebFlux 处理这种序列化场景的正确方法是什么?
解决方案
您可以自己反序列化 JSON 响应。首先将响应作为 json 获取String
,然后使用提供和配置的 Jackson 自己进行反序列化ObjectMapper
,如果有JsonMappingException
使用模型 2 的尝试。这可能不如 spring 在内部使用Jackson2JsonDecoder
它的效率高,因为它InputStream
直接处理而不创建副本但这似乎是目前使用 try/catch 方法的唯一方法。
@RestController
class Controller {
private ObjectMapper objectMapper;
public Controller(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
@GetMapping("/handler")
public Mono<Object> getHandler() {
return WebClient
.create("https://baseurl.com")
.get()
.uri("/someUri")
.retrieve()
.bodyToMono(String.class)
.flatMap(json ->
Mono.<Object>fromCallable(() -> objectMapper.readValue(json, Model1.class))
.onErrorResume(JsonMappingException.class, e ->
Mono.fromCallable(() -> objectMapper.readValue(json, Model2.class))
)
);
}
}
另一种解决方案是为响应类型创建一个基类或接口,然后JsonDeserializer
为它实现一个自定义 Jackson。这可以检测应该使用哪种类型,然后执行反序列化。
推荐阅读
- arrays - pickerview 中的条件或 if 语句
- java - 使用 ActionListener(回调)连接到 MQTT 服务器时出现错误异常
- java - 如何为 jLabel 图标的某个区域(知道坐标)着色
- python - VIM 命令插入带参数的多行文本
- python - Python Web App 通过 Heroku 服务器打开 Windows 资源管理器
- css - asciidoctor 增加 toc 宽度
- http - 在浏览器中运行我的 ionic v4 应用程序时无法进行 http 调用
- javascript - 制作一个在点击时显示隐藏图像的按钮
- drupal - 8 - 如何从模块中覆盖 DatabaQueue
- javascript - 如何在按钮单击时删除 Antd 选择/多选组件中的选定值