Controller接口反序列化顺序

需求示例

在一个Controller接口中,当Post一个请求过来,请求对象有idCardEnd、sex 两个参数。当反序列化为Java对象时如果idCardEnd为X时,表示性别一定为男,所以直接初始化。所以有了如下写法

@NoArgsConstructor
@AllArgsConstructor
public class Person {
    String idCardEnd;
    String sex;

    public String getIdCardEnd() {
        return idCardEnd;
    }

    public void setIdCardEnd(String idCardEnd) {
        this.idCardEnd = idCardEnd;
        this.sex = "X".equals(idCardEnd) ? "男": "女";
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}

问题

  1. 那么不传sex的值的时候是会根据idCardEnd去进行判断,那么两个参数同时传,结果会如何呢?
    {
     "idCardEnd":"X"
     }
    
    如果是只传一个idCardEnd,那么得到的结果是sex会根据三元表达式的判断为男
     Person(idCardEnd=X, sex=男)
    
    如果传了两个值,那个会使用sex传的值呢?还是会根据三元表达式进行判断呢?这里传一个idCardEnd=X sex = 女 试试,入参如下:
    {
     "idCardEnd":"X",
     "sex":"女"
     }
    
    得到的结果如下:
    Person(idCardEnd=X, sex=女)
    
    那么为什么会这样呢?是否跟set方法的顺序有关呢?
    我们试试将set方法的顺序换一下看
    @ToString
     @NoArgsConstructor
     @AllArgsConstructor
     public class Person {
         String idCardEnd;
         String sex;
    
         public String getIdCardEnd() {
             return idCardEnd;
         }
         public void setSex(String sex) {
             this.sex = sex;
         }
         public void setIdCardEnd(String idCardEnd) {
             this.idCardEnd = idCardEnd;
             this.sex = "X".equals(idCardEnd) ? "男": "女";
         }
    
         public String getSex() {
             return sex;
         }
     }
    
    此时我们再传一个idCardEnd=X sex = 女试试看,得到的结果如下:
    Person(idCardEnd=X, sex=女)
    
    得到的还是一样的结果,看来和Set方法的顺序是没有关系的。那么是否和传参顺序有关呢?为了控制变量,我们先将Set方法的顺序还原,更改参数顺序试试。
    {
     "sex":"女",
     "idCardEnd":"X"
     }
    
    得到的结果如下:
    Person(idCardEnd=X, sex=男)
    
    哎,这下还真和传参顺序有关,是按照传参顺序进行反序列化的。

原理分析

在一般情况下,JSON参数中的key值顺序不应该影响映射为Java对象的结果。JSON是一种键值对的无序集合,它不关心元素的排列顺序。因此,JSON中键值对的顺序理论上不应该影响到Java对象的反序列化过程。

Jackson框架通常会使用哈希表或类似的数据结构来存储JSON键值对,这些数据结构不保留元素的插入顺序。因此,在进行反序列化时,Jackson不会关心JSON中键值对的顺序。

但是,要注意的是,在某些特殊情况下,JSON中键值对的顺序可能会影响反序列化结果,这取决于具体的情况和使用的Jackson配置。例如,如果在Java对象中使用了@JsonPropertyOrder注解或者PropertyOrder类级别的注解来指定属性的顺序,那么反序列化时可能会受到这些顺序的影响。

这里我们并未使用任何干扰顺序的注解,那么是为什么呢?我们来看一下这段代码。

public void setIdCardEnd(String idCardEnd) {
    this.idCardEnd = idCardEnd;
    this.sex = "X".equals(idCardEnd) ? "男" : "女";
}

在这个方法中,setIdCardEnd方法被调用时,会将传入的idCardEnd参数值赋给this.idCardEnd属性,并且根据传入的idCardEnd参数值设置sex属性的值。

如果传参为{“sex”:“女”, “idCardEnd”:“X”},则设置sex为女,设置idCardEnd为X,然后根据条件判断设置sex为男,覆盖原来的sex为女,所以此时sex属性被设置为男。

但如果传参为{“idCardEnd”:“X”, “sex”:“女”},则设置idCardEnd为X,然后根据条件判断设置sex为男,但由于传入的sex已经为女,所以sex属性不会被重新赋值,仍然保持为女。

因此,传参顺序不同导致结果不一致的原因是,setIdCardEnd方法中的设置sex属性值的逻辑是基于传入的idCardEnd参数值进行的,而不是基于传入的sex参数值。

  • 19
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值