当前位置: 首页 > 知识库问答 >
问题:

出现错误后使用Spring WebFlux解析JSON

仲孙鸿飞
2023-03-14

我从REST API接收的JSON如下:

{
    "items": [
        {
            "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()))

响应:

public class ItemResponse {

    @JsonProperty("items")
    private List<Item> response;
}

但有时第3方API会返回不同的响应,而没有顶级项目属性,如下所示:

[
        {
            "id": 60659,
            "name": "Display",
            "active": true,
            "account_id": 235
        },
        {
            "id": 36397,
            "name": " Mail Display",
            "active": true,
            "account_id": 107
        }
]

此时,我的应用程序因JSON解码错误而崩溃。我在这种情况下使用:

bodyToMono(new ParameterizedTypeReference<List<Item>>() {})

但是我不能总是为了处理他们的json而重构这部分代码。如何使用Spring WebFlux以动态方式实现?比如< code >试着-

共有1个答案

孙夕
2023-03-14

您可以将响应作为字符串.bodyToMono(字符串.class)获取,并执行任何您想要的操作,并多次尝试捕获...但我认为你最好的选择是创建一个自定义的反序列化程序,并通过交换策略将其与你的Web客户端一起使用,如这里描述的:如何自定义SpringWebFlux Web客户端JSON反序列化? 。

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

剩下的和你的例子一样,只是改变类名和添加适当的字段。当然,这只是一个快速编写的演示,所有内容都是硬编码的,在一个方法中,最好注入它们

 类似资料:
  • 我的ThymileAF模板中有一个AngularJS属性,看起来像这样: 当Thymeleaf尝试处理此模板时,我得到以下异常: Thymeleaf只是不能很好地处理

  • 我试图实现一个单页应用程序的角度。为了使我的工作流更好,我尝试实现了Gulp。 我在安装gulp插件时遇到了一些严重的npm错误,但这是另外一个故事,我意识到,无论有没有错误,它都是工作的。 我真正碰到的是useref插件。或者更确切地说,丑陋的插件。 我想这可能是gulp做的异步工作造成的。可能是uglify插件试图丑化此时此刻未完成的useref文件。怎么知道? 所以我把所有的东西都分开了,以

  • 问题内容: 这段代码失败,并带有指示无效JSON的异常: 我可以通过用空字符串替换所有未定义内容来修复它。undefined不是JSON的一部分吗? 问题答案: 如果您可以解决这个问题,那么 令牌 实际上是未定义的。 请允许我详细说明:即使JavaScript具有称为undefined的特殊原始值,它 也不 是JavaScript关键字,也没有任何特殊含义。通过与定义对象进行比较,可以破坏测试对象

  • 问题内容: 我在解析简单的JSON字符串时遇到问题。我已经在JSONLint上检查了它们,它表明它们是有效的。但是当我尝试使用jQuery替代方法解析它们时,出现了以下错误: 注意:我正在使用PHP 对字符串进行编码。 问题答案: 您的数据已经是一个对象。无需解析。javascript解释器已经为您解析了它。

  • 本文向大家介绍python使用super()出现错误解决办法,包括了python使用super()出现错误解决办法的使用技巧和注意事项,需要的朋友参考一下 python使用super()出现错误解决办法 当我们在python的子类中调用父类的方法时,会用到super(),不过我遇到了一个问题,顺便记录一下。 比如,我写了如下错误代码: 输出报错: google之后发现,python在2.2前后有新