【BUG排查】ObjectMapper序列化前后不一致

文章讲述了在一次线上测试中,通过arthas工具发现对象判断问题,原因是未遵守变量命名规范,Lombok隐藏了这一问题。解决方法包括改变变量名、使用包装类型和注解。作者强调了在解决这类问题时要注意数据一致性,避免数据污染。
摘要由CSDN通过智能技术生成

前因

某次线上测试发现,通过 arthas 发现是对象判断不一致,代码逻辑反复检查没有问题。于是把目光放到实体类。

结果

先说结果,和人家 ObjectMapper 没啥关系,是没遵守变量命名规范导致的,lombok在这个过程中隐藏了这个问题导致没能及时发现。

解决方法

  • 改变量名字。推荐。直接治本。但是要考虑考虑在动手哦。
  • 使用包装类型,这样就不走 primitive 的命名范式。十分不推荐!
  • 在 setter 上使用 @JsonGetter([value = ] “序列化后的名字”)。临时兼容方案。
  • 在属性上加 @JsonProperty 这样 Jackson 就会知道用这个名字。临时兼容方案。

但是线上问题可不能这样粗暴的解决,会存在数据不一致的,之前的老数据不就成了脏数据了,我的处理方式是对被影响的数据进行筛选,确定范围后选个时间把正确代码更新上服务器,之后把脏数据给修复一下,修复要重复两次,避免修复过程中有新的脏数据。

排查过程

测试代码如下,可以自行尝试,记得加上依赖

public class OtherTest {
  public static void main(String[] args) {
    ObjectMapper objectMapper = new ObjectMapper();
    ObjectMapperTestModel testModel = ObjectMapperTestModel.builder()
        .isA(1)
        .isB(2)
        .enabled(true)
        .isEnabled(false)
        .build();


    try {
      String jsonStr = objectMapper.writeValueAsString(testModel);
      System.out.println("这里是序列化后的对象: " + jsonStr);

      ObjectMapperTestModel result = objectMapper.readValue(jsonStr, ObjectMapperTestModel.class);
      System.out.println("这里是反序列化后的对象: " + result.toString());
    } catch (JsonProcessingException e) {
      System.out.println("发生异常");
      throw new RuntimeException(e);
    }

  }
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class ObjectMapperTestModel {
  int isA;

  Integer isB;

  boolean enabled;

  boolean isEnabled;

}

执行结果
第一次执行结果
不知道大家有没有看出问题,isEnabled 这个变量丢了,在序列化的过程中就没了!
在这里插入图片描述
我们转到生成类中看一下, 可以发现不论是 getter 还是 setter 都没有对 isEnabled 进行操作,仿佛一开始就不存在。这就是问题原因所在。
解决这个问题很简单,但是得先知道为什么会这样,简单来说就是命名规范不对!
java bean 的命名是通过访问器(getter/setter) 决定,重点来了: boolean 类型默认使用 is<属性名> 而非优先使用 get<属性名> 作为访问器名称。原文如下在这里插入图片描述
到这里其实问题就明晰了,大家可以各显神通了。接下来是对一些解决方法的验证。

使用包装类解决

把 model 中的 isEnabled 改成 Boolean 后重新build
在这里插入图片描述
可以看到,我们钻一下文档的漏洞,人家说 boolean 类型是这样,那我用 Boolean 不就好了。事实上确实OK(仅做演示, 可别这么搞)。

使用注解( @JsonProperty / @JsonGetter)

前者是属性可用,后者是方法限定,参数填你想反序列化用哪一个属性的名称
本例中对被忽略的 isEnabled 加上 @JsonProperty("enabled")
这样的话反序列化就会使用 enabled 的值了
在这里插入图片描述

最后吐槽一下: 用工具虽然爽,但是坑也得注意才行,不然工具就和坑上的树叶一样,把坑伪装的很完美,最后得不偿失。

参考资料

  1. Java Beans API specification
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值