java 使用 Jackson 和 WebClient 将 json 数组反序列化为对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/48598233/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Deserialize a json array to objects using Hymanson and WebClient
提问by Justin
I have a problem during the deserialization of a json array using Spring. I have this json response from a service:
我在使用 Spring 反序列化 json 数组时遇到问题。我有一个来自服务的 json 响应:
[
{
"symbol": "XRPETH",
"orderId": 12122,
"clientOrderId": "xxx",
"price": "0.00000000",
"origQty": "25.00000000",
"executedQty": "25.00000000",
"status": "FILLED",
"timeInForce": "GTC",
"type": "MARKET",
"side": "BUY",
"stopPrice": "0.00000000",
"icebergQty": "0.00000000",
"time": 1514558190255,
"isWorking": true
},
{
"symbol": "XRPETH",
"orderId": 1212,
"clientOrderId": "xxx",
"price": "0.00280000",
"origQty": "24.00000000",
"executedQty": "24.00000000",
"status": "FILLED",
"timeInForce": "GTC",
"type": "LIMIT",
"side": "SELL",
"stopPrice": "0.00000000",
"icebergQty": "0.00000000",
"time": 1514640491287,
"isWorking": true
},
....
]
I get this json using the new WebClient from Spring WebFlux, here the code:
我使用来自 Spring WebFlux 的新 WebClient 获取此 json,代码如下:
@Override
public Mono<AccountOrderList> getAccountOrders(String symbol) {
return binanceServerTimeApi.getServerTime().flatMap(serverTime -> {
String apiEndpoint = "/api/v3/allOrders?";
String queryParams = "symbol=" +symbol.toUpperCase() + "×tamp=" + serverTime.getServerTime();
String signature = HmacSHA256Signer.sign(queryParams, secret);
String payload = apiEndpoint + queryParams + "&signature="+signature;
log.info("final endpoint:"+ payload);
return this.webClient
.get()
.uri(payload)
.accept(MediaType.APPLICATION_JSON)
.retrieve()
.bodyToMono(AccountOrderList.class)
.log();
});
}
AccountOrderList
账户订单列表
public class AccountOrderList {
private List<AccountOrder> accountOrders;
public AccountOrderList() {
}
public AccountOrderList(List<AccountOrder> accountOrders) {
this.accountOrders = accountOrders;
}
public List<AccountOrder> getAccountOrders() {
return accountOrders;
}
public void setAccountOrders(List<AccountOrder> accountOrders) {
this.accountOrders = accountOrders;
}
}
AccountOrder is a simple pojo that maps the fields.
AccountOrder 是一个映射字段的简单 pojo。
Actually, when I hit a get it says:
实际上,当我点击 get 时,它说:
org.springframework.core.codec.DecodingException: JSON decoding error: Cannot deserialize instance of `io.justin.demoreactive.domain.AccountOrder` out of START_ARRAY token; nested exception is com.fasterxml.Hymanson.databind.exc.MismatchedInputException: Cannot deserialize instance of `io.justin.demoreactive.domain.AccountOrder` out of START_ARRAY token
at [Source: UNKNOWN; line: -1, column: -1]
How can I deserialize the json properly using the new webflux module? What am I doing wrong?
如何使用新的 webflux 模块正确反序列化 json?我究竟做错了什么?
UPDATE 05/02/2018
更新 05/02/2018
Both answers are correct. They addressed perfectly my question but at the end I decided to use a slightly different approach:
两个答案都是正确的。他们完美地解决了我的问题,但最后我决定使用稍微不同的方法:
@Override
public Mono<List<AccountOrder>> getAccountOrders(String symbol) {
return binanceServerTimeApi.getServerTime().flatMap(serverTime -> {
String apiEndpoint = "/api/v3/allOrders?";
String queryParams = "symbol=" +symbol.toUpperCase() + "×tamp=" + serverTime.getServerTime();
String signature = HmacSHA256Signer.sign(queryParams, secret);
String payload = apiEndpoint + queryParams + "&signature="+signature;
log.info("final endpoint:"+ payload);
return this.webClient
.get()
.uri(payload)
.accept(MediaType.APPLICATION_JSON)
.retrieve()
.bodyToFlux(AccountOrder.class)
.collectList()
.log();
});
}
An alternative to this could be to return directly A Flux so you don't have to convert it to a list. (that's what flux are: a collection of n elements).
另一种方法是直接返回 A Flux ,因此您不必将其转换为列表。(这就是通量:n 个元素的集合)。
采纳答案by pvpkiran
For the response to be matched with AccountOrderList
class, json has to be like this
响应要与AccountOrderList
类匹配,json必须是这样的
{
"accountOrders": [
{
"symbol": "XRPETH",
"orderId": 12122,
"clientOrderId": "xxx",
"price": "0.00000000",
"origQty": "25.00000000",
"executedQty": "25.00000000",
"status": "FILLED",
"timeInForce": "GTC",
"type": "MARKET",
"side": "BUY",
"stopPrice": "0.00000000",
"icebergQty": "0.00000000",
"time": 1514558190255,
"isWorking": true
},
{
"symbol": "XRPETH",
"orderId": 1212,
"clientOrderId": "xxx",
"price": "0.00280000",
"origQty": "24.00000000",
"executedQty": "24.00000000",
"status": "FILLED",
"timeInForce": "GTC",
"type": "LIMIT",
"side": "SELL",
"stopPrice": "0.00000000",
"icebergQty": "0.00000000",
"time": 1514640491287,
"isWorking": true
},
....
]
}
This is what the error message says "out of START_ARRAY token"
这就是错误消息所说的“超出 START_ARRAY 令牌”
If you cannot change the response, then change your code to accept Array like this
如果您无法更改响应,请更改您的代码以接受这样的数组
this.webClient.get().uri(payload).accept(MediaType.APPLICATION_JSON)
.retrieve().bodyToMono(AccountOrder[].class).log();
You can convert this array to List and then return.
您可以将此数组转换为 List,然后返回。
回答by Pin
Regarding your updated answer to your question, using bodyToFlux
is unnecessarily inefficient and semantically doesn't make much sense either as you don't really want a stream of orders. What you want is simply to be able to parse the response as a list.
关于您对问题的更新答案,使用bodyToFlux
不必要的低效并且在语义上也没有多大意义,因为您并不真正想要订单流。您想要的只是能够将响应解析为列表。
bodyToMono(List<AccountOrder>.class)
won't work due to type erasure. You need to be able to retain the type at runtime, and Spring provides ParameterizedTypeReference
for that:
bodyToMono(List<AccountOrder>.class)
由于类型擦除而无法工作。您需要能够在运行时保留类型,Spring 提供ParameterizedTypeReference
了这一点:
bodyToMono(new ParameterizedTypeReference<List<AccountOrder>>() {})
回答by Ravi
Your response is simply List<AccountOrder>
. But, your POJO has wrapped List<AccountOrder>
. So, according to your POJO, your JSON
should be
您的回答很简单List<AccountOrder>
。但是,您的 POJO 已将List<AccountOrder>
. 所以,根据你的 POJO,你JSON
应该是
{
"accountOrders": [
{
But, you are JSON
is
但是,你JSON
是
[
{
"symbol": "XRPETH",
"orderId": 12122,
....
So, there is mismatch and failing the deserialization. You need to change to
因此,存在不匹配和反序列化失败。您需要更改为
bodyToMono(AccountOrder[].class)