Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Java序列化对字段名的影响

Java序列化对字段名的影响

作者头像
二十三年蝉
发布于 2021-03-02 07:15:11
发布于 2021-03-02 07:15:11
1.2K00
代码可运行
举报
文章被收录于专栏:闻道于事闻道于事
运行总次数:0
代码可运行

前段时间遇到一个问题,序列化之后原本类中的属性名发生了变化,原本isDel序列化之后得到的是del,为此查了一下相关资料,发现和序列化机制有关

在阿里巴巴Java开发手册中关于这一点,有过一个『强制性』规定:

为此我们要看一下POJO中布尔类型变量不同的命名

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Model1  {
    private Boolean isSuccess;
    public void setSuccess(Boolean success) {
        isSuccess = success;
    }
    public Boolean getSuccess() {
        return isSuccess;
    }
 }

class Model2 {
    private Boolean success;
    public Boolean getSuccess() {
        return success;
    }
    public void setSuccess(Boolean success) {
        this.success = success;
    }
}

class Model3 {
    private boolean isSuccess;
    public boolean isSuccess() {
        return isSuccess;
    }
    public void setSuccess(boolean success) {
        isSuccess = success;
    }
}

class Model4 {
    private boolean success;
    public boolean isSuccess() {
        return success;
    }
    public void setSuccess(boolean success) {
        this.success = success;
    }
}

以上代码的setter/getter是使用Intellij IDEA自动生成的,仔细观察以上代码,你会发现以下规律:

  • 基本类型自动生成的getter和setter方法,名称都是isXXX()setXXX()形式的。
  • 包装类型自动生成的getter和setter方法,名称都是getXXX()setXXX()形式的。

我们可以发现,虽然Model3和Model4中的成员变量的名称不同,一个是success,另外一个是isSuccess,但是他们自动生成的getter和setter方法名称都是isSuccesssetSuccess

关于Java Bean中的getter/setter方法的定义其实是有明确的规定的,根据JavaBeans(TM) Specification规定,如果是普通的参数propertyName,要以以下方式定义其setter/getter:

https://download.oracle.com/otndocs/jcp/7224-javabeans-1.01-fr-spec-oth-JSpec/

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public <PropertyType> get<PropertyName>();
public void set<PropertyName>(<PropertyType> a);

public boolean is<PropertyName>();
public void set<PropertyName>(boolean m);

可以看boolean类型的变量方法是单独定义的,使用is方式

通过对照这份JavaBeans规范,我们发现,在Model4中,变量名为isSuccess,如果严格按照规范定义的话,他的getter方法应该叫isIsSuccess。但是很多IDE都会默认生成为isSuccess。

在序列化中,这样就会受到影响

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Data
class Model3 implements Serializable {

    private static final long serialVersionUID = 1836697963736227954L;

    private Integer age;
    
    private String name;
    
    private boolean isSuccess;

    private boolean isDel;

    public String getUser(){
        return "Hello JWZ";
    }
}

我们定义一个类,使用lombok,然后看序列化进行测试

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
     //定一个Model3类型
        Model3 model3 = new Model3();
        model3.setSuccess(true);

        //使用fastjson(1.2.46)序列化model3成字符串并输出
        System.out.println("Serializable Result With fastjson :" + JSON.toJSONString(model3));

        //使用Gson(2.8.5)序列化model3成字符串并输出
        Gson gson =new Gson();
        System.out.println("Serializable Result With Gson :" +gson.toJson(model3));

        //使用jackson(2.9.6)序列化model3成字符串并输出
        ObjectMapper om = new ObjectMapper();
        System.out.println("Serializable Result With jackson :" +om.writeValueAsString(model3));

得到如下结果:

可以看到三种序列化的方式,

fastjson输出有值的数据,包含user,带is的字段被序列化不带is

Gson输出有值的数据,不包含user,带is的字段被序列化正常

Jackson输出所有有值和null的数据,包含user,带is的字段被序列化不带is

由此可以得出结论:

fastjson和Jackson是通过反射遍历getter方法,然后根据JavaBeans规则他会去掉is来获取属性值。

Gson是通过直接反射遍历类中所有属性。

现在我们试一下,对于同一个对象,如果用fastjson序列化,然后在使用Gson反序列化:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    public static void main(String[] args) {

        Model3 model3 = new Model3();
        model3.setSuccess(true);

        String fastJSONString=JSON.toJSONString(model3);

        System.out.println(fastJSONString);
        Gson gson =new Gson();
        System.out.println(gson.fromJson(fastJSONString,Model3.class));

    }

isSuccess竟然变为false

因为JSON框架通过扫描所有的getter后发现有一个isSuccess方法,然后根据JavaBeans的规范,解析出变量名为success,把model对象序列化城字符串后内容为{"success":true}

根据{"success":true}这个json串,Gson框架在通过解析后,通过反射寻找Model类中的success属性,但是Model类中只有isSuccess属性,所以,最终反序列化后的Model类的对象中,isSuccess则会使用默认值false。

因此,应尽量使用success式的命名来从源头避免这个问题。

延伸,布尔类型定义应使用Boolean还是boolean

布尔类型应该使用包装类型还是基本数据类型呢?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Test {

    public static void main(String[] args) {

        Model3 model3 = new Model3();
        System.out.println("model3 : " + model3);

    }

}

@Data
class Model3 implements Serializable {

    boolean success;

    Boolean del;
}

包装类型的默认值是null,基本类型的默认值输出了false,这在某些情况就会造成问题,建议在POJO和RPC的返回值中使用包装类型

所以在定义布尔类型变量时,应使用:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Boolean success;

参考:

《Java工程师成神之路》

《阿里巴巴Java开发手册》

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-02-23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Java中的JSON序列化和反序列化
JSON 起源于 1999 年的 JS 语言规范 ECMA262 的一个子集,后来 2003 年作为一个数据格式ECMA404(404???)发布。 2006 年,作为 rfc4627 发布,这时规范增加到 18 页,去掉没用的部分,十页不到。
鱼找水需要时间
2023/03/23
2.5K0
Java中的JSON序列化和反序列化
警惕不规范的变量命名
就在最近,项目组开始强调开发规范了,今天分享一个变量名命名不规范的小案例,强调一下规范的重要性。 Boolean变量名命名规范 16年底,阿里公开了《Java开发规范手册》,其中有一条便是“布尔类型不能以is为前缀”。规范中没有举出例子,但是给出了原因:会导致部分序列化框架的无法解析。 看看错误的示范,会导致什么问题,以Spring中的jdbcTemplate来进行实验。 定义实体类 @Entity public class Bar { @Id @GeneratedValue pr
kirito-moe
2018/04/27
2.1K0
为什么阿里强制 boolean 类型变量不能使用 is 开头?
平时工作中大家经常使用到boolean以及Boolean类型的数据,前者是基本数据类型,后者是包装类,为什么不推荐使用isXXX来命名呢?到底是用基本类型的数据好呢还是用包装类好呢?
肉眼品世界
2021/11/12
1K0
Java-json序列化和反序列化
java开发中经常会遇到json的序列化与反序列化,常用的json序列化工具有阿里的Fastjson、spring mvc内置的Jackson、还有就是我们接下来要说的谷歌的Gson。
Vincent-yuan
2021/04/01
4.9K0
【Java】Java序列化和反序列化
在Java中,序列化是将对象的状态写入字节流的机制。它主要用于Hibernate、RMI、JPA、EJB和JMS技术中。
人不走空
2024/06/28
1890
【Java】Java序列化和反序列化
Java序列化和反序列化
Java序列化(Serialize)是指将一个Java对象写入IO流中; Java反序列化(Deserialize)指的是从IO流中回复IO对象。
悠扬前奏
2019/05/28
9510
【手册详解】Java序列化引发的血案
【强制】当序列化类新增属性时,请不要修改 serialVersionUID 字段,以避免反序列失败;如果完全不兼容升级,避免反序列化混乱,那么请修改 serialVersionUID 值。说明:注意 serialVersionUID 值不一致会抛出序列化运行时异常。
chenchenchen
2022/05/07
1.1K0
【手册详解】Java序列化引发的血案
SpringBoot的序列化和反序列化
Java序列化是指把Java对象转换为字节序列的过程,而Java反序列化是指把字节序列恢复为Java对象的过程。
全栈程序员站长
2022/09/13
2.8K0
SpringBoot的序列化和反序列化
序列化Java对象重命名字段,@JSONField、@JsonProperty、@SerializedName
SerializedName 改变了默认序列化和默认反序列化的字段取值,所以,如果你使用 Gson 将 Java model 类生称 JSON 串,结果就是 value 的名称就是字段的名称。
chenchenchen
2021/09/06
15.4K0
Java 序列化
序列化分为两大部分:序列化和反序列化。序列化是这个过程的第一部分,将数据分解成字节流,以便存储在文件中或在网络上传输。反序列化就是打开字节流并重构对象。对象序列化不仅要将基本数据类型转换成字节表示,有时还要恢复数据。恢复数据要求有恢复数据的对象实例。
HLee
2021/05/08
1.2K0
Java 序列化
Java中Json字符串和Java对象的互转
Json(JavaScript Object Notation)是一种轻量级的数据交换格式。诞生于 2002 年。易于人阅读和编写。同时也易于机器解析和生成。Json 是目前主流的前后端数据传输方式。
栗筝i
2023/03/08
3.5K0
Java序列化和反序列化,你该知道得更多
序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象——百度词条解释。
用户1615728
2019/05/07
6540
Java序列化和反序列化,你该知道得更多
json 反序列化多层嵌套泛型类与 java 中的Type类型笔记
https://www.cnblogs.com/liqipeng/p/9148545.html
一个会写诗的程序员
2019/07/10
10.1K0
JSON 反序列化 Long 变 Integer 或 Double 问题
工作中可能会遇到对 Map 进行 JSON 序列化,其中值中包含 Long 类型的数据,反序列化后强转 Long 时报类型转换异常的问题。
明明如月学长
2021/10/18
3.6K0
除了闹过腥风血雨的fastjosn,你还知道哪些Java解析JSON的利器?
昨天下午 5 点 10 分左右,我解决掉了最后一个 bug,轻舒一口气,准备关机下班。可这个时候,老板朝我走来,脸上挂着神秘的微笑,我就知道他不怀好意。果不其然,他扔给了我一个新的需求,要我在 Java 中解析 JSON,并且要在半个小时候给出最佳的解决方案。
沉默王二
2020/02/17
1.4K0
[填坑篇]Java序列化与反序列化注意事项与细节探究
参与序列化的引用类型也必须实现Serializable接口,否则会报NotSerializableException异常
九转成圣
2024/04/10
2450
jackson序列化和反序列化中的注解和扩展点大全【收藏】
通过在属性、getter 方法或类级别上使用 @JsonSerialize 注解,可以指定要使用的序列化器。
公众号:码到三十五
2024/03/19
3.9K0
【小家Spring】Redis序列化、RedisTemplate序列化方式大解读,介绍Genericjackson2jsonredisserializer序列化器的坑
上一篇已经介绍了优雅的操作Redis: 【小家Spring】Spring Boot中使用RedisTemplate优雅的操作Redis,并且解决RedisTemplate泛型注入的问题。本篇着重介绍一下几种常用的序列化方式
YourBatman
2019/09/03
8K0
【小家Spring】Redis序列化、RedisTemplate序列化方式大解读,介绍Genericjackson2jsonredisserializer序列化器的坑
服务监测与redis序列化
随着服务器数量的增多,部署于不同服务器的服务数量也是稳步增长的,这时候监测每个服务是否正常运转就显得尤为重要。通过监测的结果,可以方便的知道有没有服务下线了,从而采取相应的解决策略。
时光潜流
2023/10/22
2040
服务监测与redis序列化
关于Spring Data redis几种对象序列化的比较
http://zhaozhiming.github.io/blog/2015/04/12/spring-data-redis/
逝兮诚
2019/10/30
1.8K0
推荐阅读
相关推荐
Java中的JSON序列化和反序列化
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验