错误场景

用Spring boot写了一个简单的RESTful API,在测试POST请求的时候,request body是一个符合对应实体类要求的json串,post的时候报错。

先贴一段error log:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.yucfeng.Entity.EData` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: (PushbackInputStream); line: 2, column: 2]
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67) ~[jackson-databind-2.9.5.jar:2.9.5]
at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1451) ~[jackson-databind-2.9.5.jar:2.9.5]
at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1027) ~[jackson-databind-2.9.5.jar:2.9.5]
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1290) ~[jackson-databind-2.9.5.jar:2.9.5]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:326) ~[jackson-databind-2.9.5.jar:2.9.5]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159) ~[jackson-databind-2.9.5.jar:2.9.5]

先说结论

原因:

原因是我在该实体类中添加了一个为了方便实例化该类用的构造函数,导致JVM不会添加默认的无参构造函数,而jackson的反序列化需要无参构造函数,因此报错。

Response实体类同理。

解决:

在实体类中补上一个无参构造器即可。

Jackson反序列化

通过debug,让我们来看这一部分的源码:
Jackson中有个BeanDeserializerBase类,该抽象类的子类BeanDeserializer包含了将字节流反序列化的一系列方法:如deserializeFromObject(JsonParser p, DeserializationContext ctxt)、deserialize(JsonParser p, DeserializationContext ctxt)。
在deserializeFromObject方法中,有这么一条判断语句:
if (this._nonStandardCreation)

  该属性_nonStandardCreation在BeanDeserializerBase类中是这样定义的:

this._nonStandardCreation = this._unwrappedPropertyHandler != null || this._valueInstantiator.canCreateUsingDelegate() ||
this._valueInstantiator.canCreateUsingArrayDelegate() || this._valueInstantiator.canCreateFromObjectWith() || !this._valueInstantiator.canCreateUsingDefault();

  我们把目光放到 this._valueInstantiator.canCreateUsingDefault()上:

public boolean canCreateUsingDefault() {
  return this._defaultCreator != null;
  }

  _defaultCreator表示了该实体类是否含有默认无参构造函数(通过反射机制获得)。

上文提到了,我们添加了新的构造函数,JVM并未给该实体类添加默认无参构造函数,因此_defaultCreator为null。回到最初的判断语句,这里的this._nonStandardCreation便是true。
当没有无参构造函数,BeanDeserializer会怎么处理呢?
它会尝试查找该类是否拥有_unwrappedPropertyHandler或者_externalTypeIdHandler,当然并没有。那么调用deserializeFromObjectUsingNonDefault方法进行deserialize。
protected Object deserializeFromObjectUsingNonDefault(JsonParser p, DeserializationContext ctxt) throws IOException {
  JsonDeserializer<Object> delegateDeser = this._delegateDeserializer();
  if (delegateDeser != null) {
  return this._valueInstantiator.createUsingDelegate(ctxt, delegateDeser.deserialize(p, ctxt));
  } else if (this._propertyBasedCreator != null) {
  return this._deserializeUsingPropertyBased(p, ctxt);
  } else {
  Class<?> raw = this._beanType.getRawClass();
  return ClassUtil.isNonStaticInnerClass(raw) ? ctxt.handleMissingInstantiator(raw, (ValueInstantiator)null, p, "can only instantiate non-static inner class by using default, no-argument constructor", new Object[0]) : ctxt.handleMissingInstantiator(raw, this.getValueInstantiator(), p, "cannot deserialize from Object value (no delegate- or property-based Creator)", new Object[0]);
  }
  }

  在该方法中它判断了两个属性:_delegateDeserializer和_propertyBasedCreator,对于这两个属性我也不是很明白。通过查阅API文档,前者表示委托反序列化Deserializer that is used if delegate-based creator is to be used for deserializing from JSON Object.,后者表示If the bean needs to be instantiated using constructor or factory method that takes one or more named properties as argument(s), this creator is used for instantiation(?)。最后判断一下是否是内部静态类,进入异常处理部分。

Spring Boot在反序列化过程中:jackson.databind.exc.InvalidDefinitionException cannot deserialize from Object value的更多相关文章

  1. Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.apache.catalina.connector.CoyoteWriter and no properties discovered to create BeanSerializer

    一.什么是序列化In computer science, in the context of data storage, serialization is the process of transla ...

  2. jackon - com.fasterxml.jackson.databind.exc.InvalidDefinitionException && UnrecognizedPropertyException: Unrecognized field 异常

    在用jackson解析json数据是碰到的问题 1.首先是InvalidDefinitionException 测试发现可能是目标类中无无参数构造方法导致异常. 添加无参构造方法后发现前一个异常解决但 ...

  3. com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class cn.edu.

    详细信息   https://www.cnblogs.com/xuwenjin/p/8832522.html 解决办法: 在实体类上面加上注解 @JsonIgnoreProperties(value ...

  4. Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException

    实体类缺少无参构造方法,序列化对象需要无参构造方法 @NoArgsConstructor

  5. JSON parse error: Cannot deserialize instance of `int` out of START_OBJECT token; nested exception is com.fasterxml.jackson.databind.exc

    代码程序: @PostMapping("selectById") @ResponseBody public Result selectById(@RequestBody int i ...

  6. Spring Boot 监听 Activemq 中的特定 topic ,并将数据通过 RabbitMq 发布出去

    1.Spring Boot 和 ActiveMQ .RabbitMQ 简介 最近因为公司的项目需要用到 Spring Boot , 所以自学了一下, 发现它与 Spring 相比,最大的优点就是减少了 ...

  7. spring boot 项目从配置文件中读取maven 的pom.xml 文件标签的内容。

    需求: 将pom.xml 文件中的版本号读取到配置文件并打印到日志中. 第一步: 在pom.xml 中添加以下标签. 第二步: 将version 标签的值读取到配置文件中 这里使用 @@  而不是  ...

  8. com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field 异常

    分享牛原创(尊重原创 转载对的时候第一行请注明,转载出处来自分享牛http://blog.csdn.net/qq_30739519) 1.1.1. 前言 近期在使用ObjectMapper对象将jso ...

  9. com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "ExceptionId"

    com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "Exception ...

随机推荐

  1. c# 利用反射 从json字符串 动态创建类的实例 并动态为实例成员赋值

    转自 http://hi.baidu.com/wjinbd/item/c54d43d998beb33be3108fdd 1 创建自己要用的类 class stu { string _name; int ...

  2. 向Github提交更改的代码

    更改了本地的某一文件的代码,那么如何覆盖Github上的同一文件代码呢?请看以下步骤: 1.先用 git status 看你更改了哪些文件: 2.然后 git add 你想要提交的更改的文件 或者 g ...

  3. java 从网上下载文件的几种方式

    package com.github.pandafang.tool; import java.io.BufferedOutputStream; import java.io.File; import ...

  4. mysql 12小时和24小时转换

    1.12小时显示 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); String ...

  5. 17.分支的合并&遇到冲突时的分支合并

    分支的合并 假设你已经修正了 #53 问题,并且打算将你的工作合并入 master 分支. 为此,你需要合并 iss53 分支到 master 分支,这和之前你合并 hotfix 分支所做的工作差不多 ...

  6. bitekind

    xrp这个人到SNT家坐在IOST的椅子上,喝着THETA. 武之巅峰,是孤独,是寂寞,是漫漫求索,是高处不胜寒    逆境中成长,绝地里求生,不屈不饶,才能堪破武之极道.    凌霄阁试炼弟子兼扫地 ...

  7. WebView设置透明和设置背景图片的方法

    http://blog.csdn.net/Vincent20111024/article/details/8478219 1. WebView若要设置背景图,直接设置web .setBackgroun ...

  8. Android学习——自定义控件(二)

    这篇文章来介绍自定义组合控件,自定义组合控件的应用场景很多,比如当你的UI如下时: 倘若不使用组合控件,则需要在XML文件中声明4个TextView和4个EditText,而使用了组合控件,则只需要四 ...

  9. C++11标准之右值引用(rvalue reference)

    1.右值引用引入的背景 临时对象的产生和拷贝所带来的效率折损,一直是C++所为人诟病的问题.但是C++标准允许编译器对于临时对象的产生具有完全的自由度,从而发展出了Copy Elision.RVO(包 ...

  10. 如何申请免费域名证书,以及在IIS上绑定

    1.前往https://freessl.cn/ 申请域名 证书 2.输入邮箱后,点击创建.文件验证方式 会自动下载一个压缩包,把该压缩包放到所申请的域名首层下.(不要重复创建,需要3,5分钟.最好手动 ...