如何从反应式WebClient响应中获取数据

维塔利(VitaliDzikoŭski)

我想用响应式WebClient解析来自stackexchange的一些数据,但是它抛出一个异常:

2021-02-03 23:55:17.544  INFO 16180 --- [           main] by.dzikovskiy.idt.Application            : Starting Application using Java 11.0.9.1 on DESKTOP-MT9VJGK with PID 16180 (C:\projects\WebCient\target\classes started by Vitaliy in C:\projects\WebCient)
2021-02-03 23:55:17.545  INFO 16180 --- [           main] by.dzikovskiy.idt.Application            : No active profile set, falling back to default profiles: default
2021-02-03 23:55:18.438  INFO 16180 --- [           main] o.s.b.web.embedded.netty.NettyWebServer  : Netty started on port 8081
2021-02-03 23:55:18.446  INFO 16180 --- [           main] by.dzikovskiy.idt.Application            : Started Application in 1.149 seconds (JVM running for 1.772)
Exception in thread "main" org.springframework.core.codec.DecodingException: JSON decoding error: Cannot deserialize instance of `by.dzikovskiy.idt.entity.ItemsData` out of START_ARRAY token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `by.dzikovskiy.idt.entity.ItemsData` out of START_ARRAY token
 at [Source: (io.netty.buffer.ByteBufInputStream); line: 1, column: 10] (through reference chain: by.dzikovskiy.idt.entity.StackResponse["items"])
    at org.springframework.http.codec.json.AbstractJackson2Decoder.processException(AbstractJackson2Decoder.java:228)
    Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
    |_ checkpoint ⇢ Body from GET https://api.stackexchange.com/2.2/answers?site=stackoverflow&page=1&pagesize=5&order=desc&sort=activity&filter=default [DefaultClientResponse]

我有这样的实体类

@JsonIgnoreProperties(ignoreUnknown = true)
@Data
public class StackResponse {
    private ItemsData items;
}

@JsonIgnoreProperties(ignoreUnknown = true)
@ToString
public class ItemsData {
    @JacksonXmlElementWrapper(useWrapping = false)
    List<Owner> owner;

    @JacksonXmlElementWrapper(useWrapping = false)
    public List<Owner> getOwner() {
        return owner;
    }

    public void setOwner(List<Owner> owner) {
        this.owner = owner;
    }
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonTypeName("owner")
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
public class Owner {
    @JsonProperty("user_id")
    private long userId;
    @JsonProperty("display_name")
    private String displayName;
    private String link;

}

发出请求的WebClient

@Component
public class StackResponseClient {

    private final WebClient webClient;

    @Autowired
    public StackResponseClient(WebClient webClient) {
        this.webClient = webClient;
    }

    public Mono<StackResponse> getOwners() {
        return this.webClient
                .get()
                .uri("https://api.stackexchange.com/2.2/answers?site=stackoverflow&page=1&pagesize=5&order=desc&sort=activity&filter=default")
                .accept(MediaType.APPLICATION_JSON)
                .retrieve()
                .bodyToMono(StackResponse.class);
    }

}

和主要

@SpringBootApplication
public class Application {


    public static void main(String[] args) throws JsonProcessingException {
        SpringApplication.run(Application.class, args);

        ApplicationContext ctx = new AnnotationConfigApplicationContext(Application.class);

        // code for testing json mapper
//         ObjectMapper objectMapper = new ObjectMapper();
//        StackResponse stackResponse = new StackResponse();
//        ItemsData itemsData = new ItemsData();
//        itemsData.setOwner(List.of(
//                new Owner(1,"one","link1"),
//                new Owner(2,"two","link2"),
//                new Owner(3,"three","link3")
//                ));
//        stackResponse.setItems(itemsData);
//        System.out.println(objectMapper.writeValueAsString(stackResponse));

        StackResponseClient stackResponseClient = ctx.getBean(StackResponseClient.class);

        StackResponse stackResponse = stackResponseClient.getOwners().block();
        System.out.println(stackResponse);
    }

}

我还测试了jackson ser /反序列化我的类的方式,它具有与stackexchange响应不同的json结构。也许就是这个问题。

{
    "items": {
        "owner": [
            {
                "owner": {
                    "link": "link1",
                    "user_id": 1,
                    "display_name": "one"
                }
            },
            {
                "owner": {
                    "link": "link2",
                    "user_id": 2,
                    "display_name": "two"
                }
            },
            {
                "owner": {
                    "link": "link3",
                    "user_id": 3,
                    "display_name": "three"
                }
            }
        ]
    }
}

我需要更改以获得StackResponse对象或至少像List<Owner>main这样的列表

谢谢

烘干机

我认为要反序列化的响应具有此结构

@JsonIgnoreProperties(ignoreUnknown = true)
@Data
public class Response {
    private List<Item> items;
}

Items.class

@JsonIgnoreProperties(ignoreUnknown = true)
@Data
public class Item {
    private Owner owner;
}

所有者类

@JsonIgnoreProperties(ignoreUnknown = true)
@Data
public class Owner {
    private int reputation;
    private int user_id;
    private String link;
    private String display_name;
    
    // etc. etc.

}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

反应式WebClient不发出响应

来自常规WebClient请求的Spring反应式流数据

如何在Spring反应式WebClient中返回Kotlin协程流

如何使用订阅方法在异步/反应式 webclient 请求中返回 Flux

Shiny R中的Mongodb Query使用反应式输入从数据库中获取数据

如何在 quarkus 反应式响应过滤器中添加标头?

带有反应式数据帧的反应式ggplot,在Shiny中

访问从反应式函数创建的数据以在Shiny中定义反应式值

带有文本/ html响应的反应式WebClient GET请求

如何在闪亮的反应式数据表中添加注释

如何使用反应式表单将静态数据提取到表单中

在Slick中反应式流如何用于插入数据

如何在R / Shiny中建立反应式数据框?

如何在Shiny中为反应式数据帧分配行名?

如何在反应式 mongo 数据(java)中编写来自 mongoshell 的查询

在反应式编程中如何优雅地关闭数据库连接池中的连接

如何使用间隔以反应式编程方式刷新数据?

在Shiny中修改反应式数据表的列

在闪亮的反应式结构中细分数据框

Shiny 中反应式数据框的问题

您如何从反应式微服务系统中获取数据?

如何配置反应式WebClient以使用2向TLS?

如何在 Angular 中做恢复反应式语句?

如何在反应式编程中实现热流

如何在反应式流中取消事件?

如何在 r 闪亮中创建多个反应式?

Spring Boot反应式WebClient调用旧式端点

如何将闪亮的应用程序中的反应式输入值插入MySQL数据库?

在Android反应式编程中,如何在应用过滤器后拆分流对象数据?