Jackson[1] 是我们编写 Java 应用时常用的 JSON 序列化/反序列化库。今天说说使用它的另一个技巧:为特定字段编写自己的序列化方法(或者,在序列化前,怎么先格式化特定字段)。
之前介绍过的 Jackson 的技巧:巧用 @JsonRawValue 注解。
假设某 API 返回的 JSON 结构如下:
{
"a": 10000,
"b": 12345
}
前端拿到该数据后,要做如下渲染:

即,数字要转化为「万」,且保留一位小数。
关于数值格式化,通常的做法是以下 2 种:
-
后端返回原始数值,前端拿到数值后,先格式化再显示。
-
优点:后端返回原始的数值,无需做额外的工作。 -
缺点:前端需要写格式化逻辑;当前端有多端时(web / ios / android),每一端都要写自己的格式化函数。 -
后端直接返回格式化后的字段,前端拿到数据后直接显示。
-
优点:前端只需要负责显示,无需额外逻辑;当涉及多平台时,省了前端重复的工作量。 -
缺点:后端不能偷懒了;当这些数字还需要在前端参与数学运算时,只返回格式化的文本是不够的。
本文说说采用2,让后端直接返回格式化后的字段,有没有好的实现方式。
2 的返回格式如下:
{"a":"1w","b":"1.2w"}
我们先讨论一下两种可能的实现方法。
假设有 Model 和 Dto 类如下:
@Data
class Model {
int a;
int b;
}
@Data
class Dto {
String a;
String b;
}
另外有一个格式化数值的方法:
// 格式化数值
String format(int num){
// 省略
}
方式一:手动转换
即 一个字段一个字段的拷贝,拷贝前先转换一下:
// 手动调用格式化方法
dto.setA(format(model.getA()));
dto.setB(format(model.getB()));
这种方式虽然能达到目的,但每个需要格式化的字段都需要手动调用 format 方法,就问你烦不烦?
而且,像这类从一个 bean 转换到另一个 bean 的操作,由于两边字段类型不同,也不能方便地使用 MapStruct 等工具自动转换,是不是更烦了?
所以我们引入方法二。
方法二:利用注解,声明式配置
其实,Jackson 允许我们在序列化对象时,指定某个字段的序列化方式,如下面这样:
先改写 Dto 类,保持字段类型和 Model 一致,然后给各个字段加一个注解配置:
@Data
class Dto {
@JsonSerialize(converter = MyConverter.class)
int a;
@JsonSerialize(converter = MyConverter.class)
int b;
}
其中,@JsonSerialize 注解用来进行个性化配置,converter 参数的作用,是在序列化指定字段之前,用指定转换器先进行转换操作,Jackson 再对转换后的结果进行序列化。
MyConverter 类的实现如下:
import com.fasterxml.jackson.databind.util.StdConverter;
class MyConverter
extends StdConverter<Integer, String> {
@Override
public String convert(Integer num) {
// 格式化数值
return format(num);
}
}
如此,该 Dto 中的 a、b 字段,在序列化之前,会先被格式化,即:
对于
{
"a": 10000,
"b": 12345
}
会自动转换成
{
"a": "1w",
"b": "1.2w"
}
利用注解配置的好处是:
-
当某天需求变动,不需要返回格式化的文本或格式化算法有调整时,可以通过修改 MyConverter 类来统一更改。 -
避免了每个字段都要去手动调用 format 的繁琐。 -
该注解方便在需要的地方进行复用。 -
由于 Model 和 Dto 字段名和类型一样,方便使用 MapStruct 等工具自动生成转换类。
总结
文章介绍了 Jackson 工具库在序列化 Java Bean 时,利用 @JsonSerialize 注解的 converter 配置项,可以轻松定制字段的序列化方式。该注解还有别的属性可配置,建议读者查看文档进一步学习。
参考资料
FasterXML/jackson: https://github.com/FasterXML/jackson
– END –
原文始发于微信公众号(背井):Jackson: 编写自己的字段格式化方法
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/246728.html