@ConstructorProperties注解理解以及其对应使用方式

1. 先说结论

  1. @ConstructorProperties注解并不是json里面的,而是jdk自身携带的类
    在这里插入图片描述

  2. 当一个类有多个构造函数,在进行json转化成对象的时候,需要指定其使用那个构造函数时,可以使用@ConstructorProperties注解,告诉json转化过程中,使用哪个构造函数进行反序列化为对象

  3. 默认不加任何其他条件情况下,json使用构造函数反序列化为对象时:

    1. 若有无参构造函数,以及有参构造函数时,优先会选择无参构造函数反序列化。
    2. 若有多个有参构造函数的情况下,但没有无参构造函数,优先会选择最多参数的有参构造函数反序列化。
    3. 上述两种情况,若新增条件@ConstructorProperties注解的话优先选择被该注解的构造函数反序列化。
  4. @ConstructorProperties一个注解 可以替代 json注解中的@JsonCreator与@JsonProperty同时使用的情况。

  5. 在springboot中使用@ConstructorProperties注解,其注解本身参数的功能完全失效该注解的作用只剩:告诉ObjectMapper使用那个构造函数进行反序列化,原因尚未查明。

2. 快速入门使用

1. @JsonCreator与@JsonProperty的使用

  1. @JsonCreator 指定使用那个构造函数进行反序列化

  2. @JsonProperty 指定json对象字段名字,与具体属性名字的对应关系

  3. 代码如下:

    @ToString
    public class AA {
    
        private String name;
    
        private String password;
    
        public AA(String name){
            System.out.println("使用只有一个参数的构造函数");
            this.name = name;
        }
    
    	// 指定使用该构造函数进行反序列化
    	// @JsonProperty("pwd") 指名,属性password 与json的pwd字段对应
        @JsonCreator
        public AA(@JsonProperty("name") String name, @JsonProperty("pwd") String password) {
            System.out.println("使用了全参构造函数哦");
            this.name = name;
            this.password = password;
        }
    }
    
    public class demo {
        public static void main(String[] args) throws Exception{
            String jsonStr = "{\n" +
                    "    \"name\":\"1\",\n" +
                    "    \"pwd\":\"123\"\n" +
                    "}";
    
            ObjectMapper objectMapper = new ObjectMapper();
            final AA aa = objectMapper.readValue(jsonStr, AA.class);
            System.out.println(aa);
        }
    }
    

    在这里插入图片描述

2. @ConstructorProperties使用

  1. @ConstructorProperties 完全可以替代 @JsonCreator与@JsonProperty。

  2. 注解参数是指定json字段,与 构造函数 参数的对应,绑定关系

  3. 代码如下:

    @ToString
    public class AA {
    
        private String name;
    
        private String password;
    	
    	public AA(String name){
        	System.out.println("使用只有一个参数的构造函数");
        	this.name = name;
    	}
    
    	// 该注解参数是指定json字段,与 构造函数 参数的对应
    	// 将属性password 与json的pwd字段对应
    	// 将属性namee 与json的name字段对应
        @ConstructorProperties({"name", "pwd"})
        public AA(String name, String password) {
            System.out.println("使用了全参构造函数哦");
            this.name = name;
            this.password = password;
        }
    }
    
    public class demo {
        public static void main(String[] args) throws Exception{
            String jsonStr = "{\n" +
                    "    \"name\":\"1\",\n" +
                    "    \"pwd\":\"123\"\n" +
                    "}";
    
            ObjectMapper objectMapper = new ObjectMapper();
            final AA aa = objectMapper.readValue(jsonStr, AA.class);
            System.out.println(aa);
        }
    }
    

    在这里插入图片描述

  4. 该@ConstructorProperties注解参数是指定json字段,与 构造函数 参数的对应
    将代码改成@ConstructorProperties({“pwd”, “name”})

    @ToString
    public class AA {
    
        private String name;
    
        private String password;
    
        public AA(String name) {
            System.out.println("使用只有一个参数的构造函数");
            this.name = name;
        }
        
    	// 故意将 对应关系写反
    	// 因此这里的绑定关系是:
    	// json的pwd 对应 name
    	// json的name 对应 password
        @ConstructorProperties({"pwd", "name"})
        public AA(String name, String password) {
            System.out.println("使用了全参构造函数哦");
            this.name = name;
            this.password = password;
        }
    }
    
    public class demo {
        public static void main(String[] args) throws Exception{
            String jsonStr = "{\n" +
                    "    \"pwd\":\"123\",\n" +
                    "    \"name\":\"1\"\n" +
                    "}";
    
            ObjectMapper objectMapper = new ObjectMapper();
            final AA aa = objectMapper.readValue(jsonStr, AA.class);
            System.out.println(aa);
        }
    }
    

    在这里插入图片描述
    由上图可知,原本name=1,现在则是name=123

3. 验证结论

1. 前言准备

  1. 下面的ObjectMapper,都是基于ObjectMapper,毕竟其是springboot默认使用的json转化工具。

  2. 准备一个实体类,一个controller层:

    @ToString
    public class AA {
    
        private String name;
    
        private String password;
    
        public AA(String name){
            System.out.println("使用只有一个参数的构造函数");
            this.name = name;
        }
    
        public AA(String name, String password) {
            System.out.println("使用了全参构造函数哦");
            this.name = name;
            this.password = password;
        }
    
        public AA(){
            System.out.println("使用无参构造函数");
        }
    }
    
    @RestController
    public class ConstructorTestController {
    
        @PostMapping("/test/A")
        public void testA(@RequestBody AA a){
            System.out.println(a);
        }
    }
    
  3. 在AA实体类上,只加@ToString方法,为了方便查看其属性的赋值,这里并不能增加@Getter或者@Setter注解,因为json在转化也可以基于这两个方法进行,具体可以查阅:(ObjectMapper)Json转化对象的基本原理

  4. 基于上述第三点,做个小科普,json的转化使用方式的优先级是:set方法、public的field属性、get方法、构造函数。

2. 验证无参构造与有参构造同时存在情况

  1. 无参构造与有参构造同时存在,优先级是无参构造函数
    在这里插入图片描述

  2. 若此时使用 @ConstructorProperties({“name”, “password”}),优先级则是被注解指定的构造函数

    @ToString
    public class AA {
    
        private String name;
    
        private String password;
    
        public AA(String name) {
            System.out.println("使用只有一个参数的构造函数");
            this.name = name;
        }
    
        @ConstructorProperties({"name", "password"})
        public AA(String name, String password) {
            System.out.println("使用了全参构造函数哦");
            this.name = name;
            this.password = password;
        }
    
        public AA() {
            System.out.println("使用无参构造函数");
        }
    }
    

    在这里插入图片描述

3. 验证只有 有参构造函数情况

  1. 当只有有参构造函数,无加其他任何注解,优先级则是参数最多的构造函数进行反序列化。

  2. 代码如下:

    @ToString
    public class AA {
    
        private String name;
    
        private String password;
    
        public AA(String name) {
            System.out.println("使用只有一个参数的构造函数");
            this.name = name;
        }
    
        public AA(String name, String password) {
            System.out.println("使用了全参构造函数哦");
            this.name = name;
            this.password = password;
        }
        
    }
    

    在这里插入图片描述

    有的人可能会说,因为刚刚好json有两个字段,所有才使用了全参的构造函数,现我们改成只有name字段的json请求:

    在这里插入图片描述
    由上可知,优先级:则是最多参数的构造函数

  3. 当我们使用@ConstructorProperties注解,注解参数写上 name,password
    在这里插入图片描述
    在这里插入图片描述

  4. 或者注解参数只写上name
    在这里插入图片描述

4. 在springboot中使用@ConstructorProperties注解时,参数功能完全失效

  1. 在快速入门中,我们提及到@ConstructorProperties注解的参数,是将json字段与自身构造函数的参数进行对应

  2. 但经测试,在springboot中,似乎并不是这样子,代码如下:
    对应关系为:json的字段pwd 对应 属性name,json的字段name对应属性password

    @ToString
    public class AA {
    
        private String name;
    
        private String password;
    
        public AA(String name) {
            System.out.println("使用只有一个参数的构造函数");
            this.name = name;
        }
    
        @ConstructorProperties({"pwd", "name"})
        public AA(String name, String password) {
            System.out.println("使用了全参构造函数哦");
            this.name = name;
            this.password = password;
        }
    
    }
    

    在这里插入图片描述
    在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值