• ObjectMapper反序列化中,报错不存在如默认构造函数的原因以及解决方法


    1. 前言

    1. 在工作中前后端打交道,使用最多的是json来,对于后端来说,json的转化必然少不了ObjectMapper,因此在工作中,遇到有关于ObjectMapper的一些事情记录下来。
    2. 比如这次在工作中就遇到:在json反序列化的时候,出现了报错,没有存在默认构造函数
    3. 之前写过的文章:(ObjectMapper)Json转化对象的基本原理

    2. 先说结论

    1. ObjectMapper默认的配置不使用有参构造函数进行反射创建对象,默认使用无参构造函数
    2. 从而导致使用set/get方法进行反序列化的时候,没有办法创建对象,从而无法进行set/get方法,从而报错无存在创建者,如默认构造函数。
    3. 一个类中,什么都不写构造函数情况下,默认存在无参构造函数,一旦写了其他构造函数,无参构造函数则会丢失,除非手动添加或者加@NoArgsConstructor注解。

    3. 在反序列化对象中,报错无存在默认构造函数

    1. 正常案例如下:

      public class demo {
          public static void main(String[] args) throws Exception{
              ObjectMapper objectMapper = new ObjectMapper();
      
              String jsonStr = "{\"name\":\"1\",\"age\":\"18\"}";
      
              final People people = objectMapper.readValue(jsonStr, People.class);
              System.out.println(people);
          }
      
      
          @Getter
          @ToString
          static class People {
              private String name;
              private String age;
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18

      在这里插入图片描述
      我们发现这json正常的转化为People对象了,(根据前言的(ObjectMapper)Json转化对象的基本原理)知道json转化是有set方法、构造函数方法、get方法、public的field属性方式上面的使用的是 get方法,也就是在json转化为对象的时候,当然是使用反射将对象创建出来之后,在使用get方法

    2. 当在people类上加上 @AllArgsConstructor注解,则报错如下:
      在这里插入图片描述
      报错信息是说:没有创建者,比如默认构造函数,但问题在于不是有全参的构造函数吗?为什么还是没有呢?
      这里就要解决两个问题

      1. 为什么它会觉得没有创建者?
      2. 为什么报错是说比如没有默认构造函数,那刚开始第一个代码案例也没有构造函数,怎么就成功了。
    3. 解释:
      1. 在java中,简简单单的一个class A{} 类,默认则会存在无参构造函数,但若添加了其他构造函数,则默认无参构造函数会消失,除非手动添加无参构造函数或者使用@NoArgsConstructor注解。
      2. 证明:工具(Java 如何进行反编译生成.java文件(javap、jad下载安装使用))
      代码,以及反编译之后:

      public class A {
          private String name;
      }
      
      • 1
      • 2
      • 3

      在这里插入图片描述
      在class A上加上@AllArgsConstructor之后:

      @AllArgsConstructor
      public class A {
          private String name;
      }
      
      • 1
      • 2
      • 3
      • 4

      在这里插入图片描述

      1. 从上述两张图片我们可以得出,加了@AllArgsConstructor注解的类,丢失了默认构造函数

    4. 解析以及解决方法

    1. 铺垫这么久,那么可以解释为什么在第二个案例中json转化的时候会报错了:

    2. 在第一个案例中,people类中存在默认构造函数,而是使用get方法进行反序列化的,所以在反序列化的时候,json则通过people的默认构造函数进行反射,创建了一个people对象,然后再使用get方法,将值赋予people的属性

    3. 在第二个案例中,people类上加了@AllArgsConstructor注解,导致默认构造函数不存在了,但讲道理:这个people类还是存在创建者—全参构造函数,会报错是因为ObjectMapper底层默认是通过一个类的无参构造函数进行反射创建对象的

    4. 而我们也可以改变这个配置(注springboot中在自动装载的时候,已经默认配了):

      public class demo {
          public static void main(String[] args) throws Exception{
              ObjectMapper objectMapper = new ObjectMapper()
              		// 注册自定义模式
                      .registerModule(new ParameterNamesModule(JsonCreator.Mode.DEFAULT));
      
              String jsonStr = "{\"name\":\"1\",\"age\":\"18\"}";
      
              final People people = objectMapper.readValue(jsonStr, People.class);
              System.out.println(people);
          }
      
      
          @Getter
          @AllArgsConstructor
          @ToString
          static class People {
              private String name;
              private String age;
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21

      在这里插入图片描述

      // 解释:
      1. registerModule 注册自定义模式,简单理解是指使用类的构造函数的配置
      2. new ParameterNamesModule() 可不传入值,代表可使用有参构造函数创建对象
      3. JsonCreator.Mode 创建者的模式,即就是使用有参构造函数的设置
      4. Mode的值如下4个:
      	1. DEFAULT:默认,无特殊处理
      	2. DELEGATING:只使用一个有参的构造函数
      	3. PROPERTIES:使用多个有参的构造函数
      	4. DISABLED:禁止使用有参构造函数
       ObjectMapper objectMapper = new ObjectMapper()
                  .registerModule(new ParameterNamesModule(JsonCreator.Mode.DEFAULT));
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
    5. 在springboot的默认配置位置:
      在这里插入图片描述

  • 相关阅读:
    代码讲解 Java注解详解和自定义注解实战
    Linux Mint(Ubuntu)上 安装 效率神器 utools
    java datetime数据类型去掉时分秒
    Lua解释器裁剪
    2024年仁爱学院专升本招生专业对应范围专业目录更新的通知
    多因素身份认证之手机推送认证
    【OpenCV】直方图计算 & 均衡化直方图
    Cadence OrCAD Capture 关键网络逐个检查方法
    JAVA-读取excel转成html 将excel表格转换为HTML文件格式 转成前端表格样式
    MTK平台双击Power打开Camera的简单流程
  • 原文地址:https://blog.csdn.net/xueyijin/article/details/126320916