栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Vert.x web 接收请求时反序列化对象 Failed to decode 如何解决?

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Vert.x web 接收请求时反序列化对象 Failed to decode 如何解决?

最近在尝试用 Vert.x 进行 web 开发,发现接口在接收请求体后,反序列化报错,跟进一下原因。

目录
    • 解决方案
    • 排查过程
      • 构造接口
      • 发现问题
      • 跟进代码
      • 如何切换 Databind 实现?

解决方案

引入 jackson-databind
我是用的是 Vert.x 4.3.1,所以引入 jackson-databind 2.13.2.* 版本:


    com.fasterxml.jackson.core
    jackson-databind
    2.13.2.2

排查过程 构造接口

编写一个 Post 接口,将请求体转换为一个对象 NewOrderRequest(对象是个 DTO,只有一些基本的字段定义):

import io.vertx.core.Future;
import io.vertx.core.Vertx;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.RoutingContext;
import io.vertx.ext.web.handler.BodyHandler;
import io.vertx.sqlclient.Pool;

public class OrderRestAPI {
    
    private final OrderService orderService;

    public OrderRestAPI(Vertx vertx, Router router, Pool pool, JsonObject orderConfig) {
        orderService = new OrderService(vertx, pool, orderConfig);
        router.post("/order").handler(BodyHandler.create().setBodyLimit(256)).respond(this::newOrder);
    }

    private Future> newOrder(RoutingContext ctx) {
        NewOrderRequest newOrderRequest = ctx.body().asPojo(NewOrderRequest.class);
        return orderService.newOrder(newOrderRequest).map(result -> new ResponseDTO<>("OK", result));
    }
}
发现问题

但是在反序列化的时候报错 Failed to decode:

22:25:50.048 [vert.x-eventloop-thread-1] ERROR io.vertx.ext.web.RoutingContext - Unhandled exception in router
io.vertx.core.json.DecodeException: Failed to decode
	at io.vertx.core.json.jackson.JacksonCodec.cast(JacksonCodec.java:350) ~[vertx-core-4.3.1.jar:4.3.1]
	at io.vertx.core.json.jackson.JacksonCodec.fromParser(JacksonCodec.java:187) ~[vertx-core-4.3.1.jar:4.3.1]
	at io.vertx.core.json.jackson.JacksonCodec.fromBuffer(JacksonCodec.java:74) ~[vertx-core-4.3.1.jar:4.3.1]
	at io.vertx.core.json.Json.decodeValue(Json.java:119) ~[vertx-core-4.3.1.jar:4.3.1]
	at io.vertx.ext.web.impl.RequestBodyImpl.asPojo(RequestBodyImpl.java:126) ~[vertx-web-4.3.1.jar:4.3.1]
	at io.vertx.ext.web.RequestBody.asPojo(RequestBody.java:115) ~[vertx-web-4.3.1.jar:4.3.1]
	at icu.wwj.web.handler.OrderRestAPI.newOrder(OrderRestAPI.java:25) ~[classes/:?]
跟进代码

查看 Vert.x JacksonCodec 发现,请求体被正常反序列化为了 LinkedHashMap,但是代码中判断,如果反序列化的目标不是 Map 或着 Map 的派生,就抛出 Failed to decode 的错误:

看到上面的代码首先感到的是奇怪:

  • 为什么非常简单的对象反序列化也无法进行?
  • 是不是我是用 asPojo 的方式不对?

往上层看了下,Vert.x 不出所料地使用了流行的 Jackson,但是 JsonCodec 方法有两个实现:

  • DatabindCodec
  • JacksonCodec

    目前运行的进程默认使用了 JacksonCodec,是不是可以切换到 DatabindCodec 试试?
如何切换 Databind 实现?

Vert.x 通过 JacksonFactory 创建 JsonCodec 的实现,先尝试创建 DatabindCodec,如果抛出异常(也就是缺少 databind 相关的类)则创建 JacksonCodec:

public class JacksonFactory implements io.vertx.core.spi.JsonFactory {

  public static final JacksonFactory INSTANCE = new JacksonFactory();

  public static final JacksonCodec CODEC;

  static {
    JacksonCodec codec;
    try {
      codec = new DatabindCodec();
    } catch (Throwable ignore) {
      // No databind
      codec = new JacksonCodec();
    }
    CODEC = codec;
  }

  @Override
  public JsonCodec codec() {
    return CODEC;
  }
}

源码链接:https://github.com/eclipse-vertx/vert.x/blob/0bdaecf62dbb14421d0277fbfe3c90a47812f538/src/main/java/io/vertx/core/json/jackson/JacksonFactory.java

vertx-core 在引入 jackson-databind 的时候声明了 optional:

    
    
      com.fasterxml.jackson.core
      jackson-core
    
    
      com.fasterxml.jackson.core
      jackson-databind
      true
    

源码链接:https://github.com/eclipse-vertx/vert.x/blob/0bdaecf62dbb14421d0277fbfe3c90a47812f538/pom.xml#L127-L136

由此可以理解:Vert.x Core 引入了 jackson-core 以提供基本的 Json 编解码能力,但对于 Json 与对象映射这类更高级的操作,需要借助 jackson-databind 实现。

那只需要引入 jackson-databind 就能解决问题了。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/999463.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号