当匈牙利命名法遇到 JAVA 会怎么样?

不过……事情并没有那么简单。后端不会将所有的报文都作为 POJO 的字段,会存在一些动态的字段,用 Map 存储。可 Map 存储的这些字段,Jackson 在输出时不会转为小写,还是保留原有的大写形式,这样就会导致给前端的字段,虽然都是匈牙利风格,但有些大写有些小写……虽然前端不知道打不打人,但我可不敢这么玩

不同序列化库的处理机制不同


Jackson 的匈牙利命名法处理

其实 Jackson 序列化之后转小写的原因也很好解释,Java 的设计规范,就是 Bean 中的属性用 private 修饰,然后提供 getter/setter 来提供读取/写入。那么在序列化时,Jackson 通过字段的 Getter 来访问属性值,甚至用 Getter 方法来解析属性名。 ​

Java 的 getter 方法命名标准是,将小写驼峰转大写驼峰,Jackson 在通过 getter 方法名解析字段名时,将 getNID 解析为 nid 了,所以导致最终输出的字段名为小写的 nid。

FastJson 的匈牙利命名法处理

本来是想定制化一下 Jackson 的命名处理的,但想了一下觉得没必要,毕竟是我们命名不标准,何必去改这个命名处理机制呢,划不来。 ​

所以我又尝试着换一种 JSON 库去处理这个命名问题,先试试阿里的 FastJSON,看看这个国产库的处理怎么样:

{

“cTitle”:“Effective JAVA”,

“nId”:1

}

看到这个序列化结果时,我差点把我键盘上的 Backspace 按断了……同样是通过 getter 方法解析属性名,两个库的解析规则还能不一样…… ​

在 FastJson 里,c 是小写了,可 Title 里的 T 还是大写,@#¥%……&此处省略100字…… ​

冷静一下之后,心里默念了几遍:“不怪别人,是我们自己的命名问题,不符合标准人家怎么解析都不关你事……” ​

不过 JAVA 的生态这么好,JSON 库也不止这两个,再换一个就是,Google 的 Gson 也很不错嘛!

Gson 的匈牙利命名法

于是我又换成了 Gson,配置完 Spring MVC Gson Converter 之后,输出结果:

{

“NId”:1,

“CTitle”:“Effective JAVA”

}

终于换到一个能正常显示原始字段名的 JSON 库了,不过它既然能保持原有字段名,而不是 getter 里解析的属性名,那么它肯定不是解析 getter 方法名的 ​

于是我又去翻了下 Gson 的源码,发现它是直接 getDeclaredFields(),然后makeAccessible,最后直接通过 Field.getValue的方式直接获取属性值的。 ​

相比 Jackson 和 FastJson 里通过 getter 获取属性列表,然后通过调用 getter 方法来获取属性值的方法来说,强制访问私有属性这种做法还是太暴力了,不过我喜欢,至少它能轻松解决了我的问题

其他的序列化问题

除了 JSON 这种文本形式的序列化之外,一些二进制的序列化也会有这个尴尬的问题,获取属性列表/属性值,到底是用解析 getter 方法的方式,还是直接 makeAccessible 暴力访问私有属性呢? ​

这个我测试了一下,比如在 Dubbo 的默认序列化方式(Dubbo 简化的Hession2)中,仍然是 getDeclaredFields,然后访问私有属性 ​

在 JDK 的内置序列化 ObjectOutputStream 中,也是 getDeclaredFields,然后访问私有属性。 ​

不过这种 getDeclaredFields ,然后访问私有属性值的方式,也会有一些劣势。比如在遇到代码混淆时,私有属性的值会被全部打乱,而 public 的方法却不会,所以在遇到混淆的代码时,这种方式就会乱套了,而通过 getter 方法解析的方式就不会有问题。 ​

所以吧,这个获取属性的方式并没有对错,怎么都可以,不过我认为还是应该通过 getter/setter 的方式来操作,符合 JAVA 的规范。

补充


感谢@用户3323102545477 的提醒,Jackson 很强大,支持配置属性的获取方式,可以配置 Visibility 来实现只通过 Field 而不通过 getter 来获取属性:

@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY,

getterVisibility = JsonAutoDetect.Visibility.NONE)

public class Book {

private Integer NId = 1;

private String CName = “John”;

}

全局配置更方便:

ObjectMapper objectMapper = new ObjectMapper();

// 配置 field 为可见

objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);

// 配置 getter 不可见

objectMapper.setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.NONE);

总结


Java 里访问私有属性值,标准的方式是通过 getter 方法,但还是提供了一个 makeAccessible 操作,可以让我们直接访问私有属性或者私有方法。 ​

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
img

最后

手绘了下图所示的kafka知识大纲流程图(xmind文件不能上传,导出图片展现),但都可提供源文件给每位爱学习的朋友

image.png

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
[外链图片转存中…(img-U7yBRfBJ-1710421131152)]

最后

手绘了下图所示的kafka知识大纲流程图(xmind文件不能上传,导出图片展现),但都可提供源文件给每位爱学习的朋友

[外链图片转存中…(img-i92mzRQj-1710421131152)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

  • 23
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值