Java 发生错误后使用SpringWebFlux解析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 }, {

我从REST API接收JSON,如下所示:

{
    "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()))
}