使用 Jackson 和 WebClient 将 json 数组反序列化为对象 [英] Deserialize a json array to objects using Jackson and WebClient

查看:56
本文介绍了使用 Jackson 和 WebClient 将 json 数组反序列化为对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用 Spring 反序列化 json 数组时遇到问题.我有一个来自服务的 json 响应:

<预><代码>[{"符号": "XRPETH",订单编号":12122,"clientOrderId": "xxx","价格": "0.00000000","origQty": "25.00000000","executedQty": "25.00000000","状态": "已满","timeInForce": "GTC","type": "市场","side": "买入","stopPrice": "0.00000000","icebergQty": "0.00000000",时间":1514558190255,正在工作":真},{"符号": "XRPETH",订单号":1212,"clientOrderId": "xxx","价格": "0.00280000","origQty": "24.00000000","executedQty": "24.00000000","状态": "已满","timeInForce": "GTC",类型":限制","side": "卖","stopPrice": "0.00000000","icebergQty": "0.00000000",时间":1514640491287,正在工作":真},....]

我使用来自 Spring WebFlux 的新 WebClient 获取此 json,代码如下:

@Overridepublic MonogetAccountOrders(字符串符号){返回 binanceServerTimeApi.getServerTime().flatMap(serverTime -> {String apiEndpoint = "/api/v3/allOrders?";String queryParams = "symbol=" +symbol.toUpperCase() + "&timestamp=" + serverTime.getServerTime();字符串签名 = HmacSHA256Signer.sign(queryParams, secret);字符串有效负载 = apiEndpoint + queryParams + "&signature="+signature;log.info("最终端点:"+有效载荷);返回 this.webClient.得到().uri(有效载荷).accept(MediaType.APPLICATION_JSON).取回().bodyToMono(AccountOrderList.class).日志();});}

账户订单列表

公共类 AccountOrderList {私人列表<AccountOrder>账户订单;公共 AccountOrderList() {}public AccountOrderList(List accountOrders) {this.accountOrders = accountOrders;}公共列表<AccountOrder>getAccountOrders() {返回帐户订单;}public void setAccountOrders(List accountOrders) {this.accountOrders = accountOrders;}}

AccountOrder 是一个映射字段的简单 pojo.

实际上,当我点击 get 时,它会说:

org.springframework.core.codec.DecodingException:JSON 解码错误:无法从 START_ARRAY 令牌中反序列化 `io.justin.demoreactive.domain.AccountOrder` 的实例;嵌套异常是 com.fasterxml.jackson.databind.exc.MismatchedInputException:无法从 START_ARRAY 令牌反序列化 `io.justin.demoreactive.domain.AccountOrder` 的实例在 [来源:未知;行:-1,列:-1]

如何使用新的 webflux 模块正确反序列化 json?我究竟做错了什么?

更新 05/02/2018

两个答案都是正确的.他们完美地解决了我的问题,但最后我决定使用稍微不同的方法:

@Overridepublic Mono>getAccountOrders(字符串符号){返回 binanceServerTimeApi.getServerTime().flatMap(serverTime -> {String apiEndpoint = "/api/v3/allOrders?";String queryParams = "symbol=" +symbol.toUpperCase() + "&timestamp=" + serverTime.getServerTime();字符串签名 = HmacSHA256Signer.sign(queryParams, secret);字符串有效负载 = apiEndpoint + queryParams + "&signature="+signature;log.info("最终端点:"+有效载荷);返回 this.webClient.得到().uri(有效载荷).accept(MediaType.APPLICATION_JSON).取回().bodyToFlux(AccountOrder.class).collectList().日志();});}

另一种方法是直接返回 A Flux,这样您就不必将其转换为列表.(这就是通量:n 个元素的集合).

解决方案

要匹配AccountOrderList类的响应,json必须是这样的

<代码>{帐户订单":[{"符号": "XRPETH",订单编号":12122,"clientOrderId": "xxx","价格": "0.00000000","origQty": "25.00000000","executedQty": "25.00000000","状态": "已满","timeInForce": "GTC","type": "市场","side": "买入","stopPrice": "0.00000000","icebergQty": "0.00000000",时间":1514558190255,正在工作":真},{"符号": "XRPETH",订单号":1212,"clientOrderId": "xxx","价格": "0.00280000","origQty": "24.00000000","executedQty": "24.00000000","状态": "已满","timeInForce": "GTC",类型":限制","side": "卖","stopPrice": "0.00000000","icebergQty": "0.00000000",时间":1514640491287,正在工作":真},....]}

这是错误消息所说的超出 START_ARRAY 令牌"

如果你不能改变响应,那么改变你的代码来接受这样的数组

this.webClient.get().uri(payload).accept(MediaType.APPLICATION_JSON).retrieve().bodyToMono(AccountOrder[].class).log();

你可以把这个数组转成List然后返回.

I have a problem during the deserialization of a json array using Spring. I have this json response from a service:

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

@Override
    public Mono<AccountOrderList> getAccountOrders(String symbol) {
        return binanceServerTimeApi.getServerTime().flatMap(serverTime -> {
            String apiEndpoint = "/api/v3/allOrders?";
            String queryParams = "symbol=" +symbol.toUpperCase() + "&timestamp=" + 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.

Actually, when I hit a get it says:

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.jackson.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?

UPDATE 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() + "&timestamp=" + 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).

解决方案

For the response to be matched with AccountOrderList class, json has to be like this

{
  "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"

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.

这篇关于使用 Jackson 和 WebClient 将 json 数组反序列化为对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆