Java 发生错误后使用SpringWebFlux解析JSON
我从REST API接收JSON,如下所示:Java 发生错误后使用SpringWebFlux解析JSON,java,spring,spring-webflux,project-reactor,Java,Spring,Spring Webflux,Project Reactor,我从REST API接收JSON,如下所示: { "items": [ { "id": 60659, "name": "Display", "active": true, "account_id": 235 }, {
{
"items": [
{
"id": 60659,
"name": "Display",
"active": true,
"account_id": 235
},
{
"id": 36397,
"name": " Mail Display",
"active": true,
"account_id": 107
}
]
}
[
{
"id": 60659,
"name": "Display",
"active": true,
"account_id": 235
},
{
"id": 36397,
"name": " Mail Display",
"active": true,
"account_id": 107
}
]
我使用这个方法来解析它:
Mono<List<Item>> getItems(String token) {
return webCLient
.get()
.headers(httpHeaders -> httpHeaders.setBearerAuth(token))
.retrieve()
.bodyToMono(ItemResponse.class)
.map(ItemResponse::getResponse)
.retryBackoff(RetrySettings.RETRIES, RetrySettings.FIRST_BACKOFF, RetrySettings.MAX_BACKOFF)
.doOnError(e -> log.error("error: " + e.getCause().toString()))
此时,我的应用程序因JSON解码错误而崩溃。我在本案例中使用:
bodyToMono(new ParameterizedTypeReference<List<Item>>() {})
bodytomino(新的参数化类型引用(){})
但我不能总是重构这部分代码来处理json。如何使用Spring WebFlux以动态方式进行此操作?比如
try->parse#1->catch->parse#2
。因此,我需要以方式1解析json,如果出现错误,应用程序应该尝试以方式2解析它。您可以以字符串的形式获得响应。bodyToMono(string.class)
并执行您想要的任何操作,同时使用多个try-catch。。。但我认为最好的办法是创建一个自定义的反序列化程序
,并通过ExchangeStategies
将其与您的WebClient一起使用,如下所述:
类MyResponse{
列出数据;
MyResponse(列表数据){
这个数据=数据;
}
}
类MyResponseDeserializer扩展了JsonDeserializer{
@凌驾
公共MyResponse反序列化(JsonParser JsonParser,DeserializationContext DeserializationContext)引发IOException{
TreeNode TreeNode=jsonParser.getCodec().readTree(jsonParser);
列表数据=新的ArrayList();
if(treeNode.isArray()){
//将其解析为数组
}否则{
//将其解析为对象并放入列表中
}
MyResponse MyResponse=新的MyResponse(数据);
返回myResponse;
}
}
然后
WebClient getWebClient() {
ObjectMapper objectMapper = new ObjectMapper();
SimpleModule simpleModule = new SimpleModule();
simpleModule.addDeserializer(MyResponse.class, new MyResponseDeserializer());
objectMapper.registerModule(simpleModule);
ExchangeStrategies strategies = ExchangeStrategies
.builder()
.codecs(clientDefaultCodecsConfigurer -> {
clientDefaultCodecsConfigurer.defaultCodecs().jackson2JsonEncoder(new Jackson2JsonEncoder(objectMapper, MediaType.APPLICATION_JSON));
clientDefaultCodecsConfigurer.defaultCodecs().jackson2JsonDecoder(new Jackson2JsonDecoder(objectMapper, MediaType.APPLICATION_JSON));
}).build();
return WebClient.builder().exchangeStrategies(strategies).build();
}
Mono<List<Item>> getItems(String token) {
return getWebClient()
.get()
.headers(httpHeaders -> httpHeaders.setBearerAuth(token))
.retrieve()
.bodyToMono(MyResponse.class)
.map(MyResponse::data)
.retryBackoff(RetrySettings.RETRIES, RetrySettings.FIRST_BACKOFF, RetrySettings.MAX_BACKOFF)
.doOnError(e -> log.error("error: " + e.getCause().toString()))
}
WebClient getWebClient(){
ObjectMapper ObjectMapper=新的ObjectMapper();
SimpleModule SimpleModule=新的SimpleModule();
simpleModule.addDeserializer(MyResponse.class,新的MyResponseDeserializer());
registerModule(simpleModule);
ExchangeStrages策略=ExchangeStrages
.builder()
.codecs(客户端默认codecsconfigurer->{
ClientDefaultCodesconfigurer.defaultCodecs().jackson2JsonEncoder(新的jackson2JsonEncoder(objectMapper,MediaType.APPLICATION_JSON));
ClientDefaultCodecsConfiger.defaultCodecs().jackson2JsonDecoder(新的jackson2JsonDecoder(objectMapper,MediaType.APPLICATION_JSON));
}).build();
返回WebClient.builder().ExchangeStategies(strategies.build();
}
Mono getItems(字符串标记){
返回getWebClient()
.get()
.headers(httpHeaders->httpHeaders.setbearauth(令牌))
.retrieve()
.bodyToMono(MyResponse.class)
.map(MyResponse::data)
.retryBackoff(RetrySettings.RETRIES,RetrySettings.FIRST\u BACKOFF,RetrySettings.MAX\u BACKOFF)
.doError(e->log.error(“错误:+e.getCause().toString()))
}
其余部分与示例中相同,只需更改类名并添加适当的字段。
当然,这只是一个快速编写的演示,所有内容都是硬编码的,在一个方法中,最好将它们注入第二个响应不是有效的json,应该从源代码处修复,因为它提供了中断的响应,但是如果解析失败,您可以返回一个Mono#错误
,然后使用onErrorResume
以另一种方式解析它。我修复了json,这是我的错。你能举个例子吗?我用SpringWebFlux工作了几个小时。不,我不能提供一个有效的例子,如果你只用它工作了几个小时,我建议你在提出堆栈溢出问题之前,先阅读更多关于如何使用它的内容,然后至少试着发布你尝试过的内容和失败的原因。作为开发人员,这是学习过程的一部分。
class MyResponse {
List<Object> data;
MyResponse(List<Object> data) {
this.data = data;
}
}
class MyResponseDeserializer extends JsonDeserializer<MyResponse> {
@Override
public MyResponse deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
TreeNode treeNode = jsonParser.getCodec().readTree(jsonParser);
List<Object> data = new ArrayList<>();
if (treeNode.isArray()) {
// parse it as array
} else {
// parse it as object and put inside list
}
MyResponse myResponse = new MyResponse(data);
return myResponse;
}
}
WebClient getWebClient() {
ObjectMapper objectMapper = new ObjectMapper();
SimpleModule simpleModule = new SimpleModule();
simpleModule.addDeserializer(MyResponse.class, new MyResponseDeserializer());
objectMapper.registerModule(simpleModule);
ExchangeStrategies strategies = ExchangeStrategies
.builder()
.codecs(clientDefaultCodecsConfigurer -> {
clientDefaultCodecsConfigurer.defaultCodecs().jackson2JsonEncoder(new Jackson2JsonEncoder(objectMapper, MediaType.APPLICATION_JSON));
clientDefaultCodecsConfigurer.defaultCodecs().jackson2JsonDecoder(new Jackson2JsonDecoder(objectMapper, MediaType.APPLICATION_JSON));
}).build();
return WebClient.builder().exchangeStrategies(strategies).build();
}
Mono<List<Item>> getItems(String token) {
return getWebClient()
.get()
.headers(httpHeaders -> httpHeaders.setBearerAuth(token))
.retrieve()
.bodyToMono(MyResponse.class)
.map(MyResponse::data)
.retryBackoff(RetrySettings.RETRIES, RetrySettings.FIRST_BACKOFF, RetrySettings.MAX_BACKOFF)
.doOnError(e -> log.error("error: " + e.getCause().toString()))
}