目录
- 前言
- 1. 核心知识
- 2. 基本知识
- 3. Demo
- 3.1 jsontest1
- 3.2 jsontest2
- 4. 总结
前言
对应序列化的相关知识可看我之前的文章:详解Java中的serialVersionUID概念以及作用(附上Demo)
通过理解核心知识,再去品味总结的基本知识,可能理解更加透彻
对于序列化的场景,也可用于序列化JSON数据给前端的时候,某些值如果为空的时候,需要返回给前端的状态信息,对应需要使用到@JsonSerialize
1. 核心知识
@JsonSerialize
是 Jackson 库中的一个注解,用于指定在将 Java 对象序列化为 JSON 格式时,如何进行自定义的序列化处理。
通过这个注解,指定一个自定义的序列化器(serializer),以控制对象的序列化过程。
通过代码看总结:
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
// 继承 JsonSerializer<T> 实现自定义序列化逻辑
public class CustomSerializer extends JsonSerializer<MyObject> {
@Override
public void serialize(MyObject value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
// 在这里定义自己的序列化逻辑
gen.writeString(value.toString());
}
}
在Jackson库中,为了实现自定义的序列化逻辑,通常会创建一个类,该类继承自 JsonSerializer<T>
接口或其子类。JsonSerializer<T>
是一个泛型接口,其中的 <T>
表示要序列化的对象的类型。
继承 JsonSerializer<T>
接口的主要目的是为了实现 serialize 方法,该方法定义了如何将指定类型的对象序列化为 JSON 格式。
通过继承该接口,提供自定义的序列化逻辑,从而满足特定对象的序列化需求。
具体来说,继承 JsonSerializer<T>
需要实现以下方法:
serialize(T value, JsonGenerator gen, SerializerProvider serializers):
该方法定义了如何将对象 value 序列化为 JSON 格式,并使用 JsonGenerator 对象进行输出。
2. 基本知识
常使用的using以及nullsUsing
JsonSerialize 注解
: 用于指定自定义序列化器的注解。JsonSerializer 接口
: 自定义序列化器需要实现这个接口,然后通过@JsonSerialize
注解的 using 属性指定使用哪个序列化器。
该注解可以应用在类中,也可应用在属性中,对类的不同属性使用不同的序列化逻辑,从而更加灵活地控制 JSON 序列化的过程。
除了using的注解也还有nullsUsing 等注解,@JsonSerialize(nullsUsing = xx.class)
的含义是,当某个属性的值为 null 时,使用指定的自定义序列化器 xx.class
来处理该属性的序列化。
-
nullsUsing
: 该属性用于指定在属性值为 null 时使用的序列化器。 -
xx.class:
自定义的序列化器类,它实现了 Jackson 的 JsonSerializer 接口,定义了处理 null 值的序列化逻辑。
示例代码如下:
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
// 自定义处理 null 值的序列化器
class NullSerializer extends JsonSerializer<Object> {
@Override
public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
// 在这里定义处理 null 值的序列化逻辑
gen.writeString("CustomNullValue");
}
}
// 包含使用 @JsonSerialize 注解的类
class MyClass {
// 当属性值为 null 时,使用 NullSerializer 处理序列化
@JsonSerialize(nullsUsing = NullSerializer.class)
private String nullableField;
// 其他属性和方法...
}
在上述例子中,nullableField
属性上使用了 @JsonSerialize(nullsUsing = NullSerializer.class)
注解。当 nullableField
的值为 null 时,将使用 NullSerializer 类中定义的逻辑来处理该属性的序列化。
在这个例子中,处理 null 值的逻辑是将其序列化为字符串 "CustomNullValue"
。
总的来说,其作用如下:
定制化需求
: 继承可以提供更大的灵活性,允许开发者完全控制序列化过程。特定类型处理
: 可以为不同类型的对象创建不同的序列化逻辑,以满足特定的业务需求。重用性
: 可以将自定义序列化器用于多个类,提高代码的重用性。
总的来说,通过继承 JsonSerializer<T>
接口,开发者可以更加精细地控制对象的序列化过程,以适应各种复杂的场景和需求。
3. Demo
假设有一个包含日期信息的类 CustomDate,并且将其序列化为 JSON 格式时,按照特定的格式输出日期。
通过继承 JsonSerializer<T>
来实现自定义的日期序列化逻辑。
注意看两个Demo的区分,分别应用在类或者属性上,以及使用using或者nullsUsing的区别!
3.1 jsontest1
注解应用在类上,且属性都会被序列化为某个特性:
对于序列化的方式如下:
package com.example.demo;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
// 自定义序列化器
class CustomDateSerializer extends JsonSerializer<CustomDate> {
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 在这里定义自己的序列化逻辑
@Override
public void serialize(CustomDate customDate, JsonGenerator gen, SerializerProvider serializers) throws IOException {
Date date = customDate.getDate();
String formattedDate = dateFormat.format(date);
gen.writeString(formattedDate);
}
}
// 被序列化的对象
@JsonSerialize(using = CustomDateSerializer.class)
class CustomDate {
private Date date;
public CustomDate(){}
public CustomDate(Date date) {
this.date = date;
}
public Date getDate() {
return date;
}
}
public class jsontest1 {
public static void main(String[] args) throws IOException {
// 创建一个 实例
CustomDate customDate = new CustomDate(new Date());
// 使用 Jackson 库将 MyObject 序列化为 JSON 字符串
String json = new ObjectMapper().writeValueAsString(customDate);
// 输出结果
System.out.println(json);
}
}
截图如下:
3.2 jsontest2
对应序列化的类如下:(序列化的值为空!)
class CustomDateSerializer extends JsonSerializer<CustomDate> {
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 在这里定义自己的序列化逻辑
@Override
public void serialize(CustomDate customDate, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeString("");
}
}
其运行的主函数如下:(注意传输的值为空!)
public class jsontest2 {
public static void main(String[] args) throws IOException {
// 创建一个 实例
CustomDate customDate = new CustomDate();
// 使用 Jackson 库将 MyObject 序列化为 JSON 字符串
String json = new ObjectMapper().writeValueAsString(customDate);
// 输出结果
System.out.println(json);
}
}
如果代码为如下:
class CustomDate {
@JsonSerialize(using = CustomDateSerializer.class)
private Date date;
public CustomDate(){}
public CustomDate(Date date) {
this.date = date;
}
public Date getDate() {
return date;
}
}
输出结果为:(这说明序列化失败),但注意如果这样放在类上,是可以成功的!
为了在属性上可以序列化,应该使用如下方式:
class CustomDate {
@JsonSerialize(nullsUsing = CustomDateSerializer.class)
private Date date;
public CustomDate(){}
public CustomDate(Date date) {
this.date = date;
}
public Date getDate() {
return date;
}
}
截图如下所示:
对应的将该注解放在类上,序列化可以成功!
4. 总结
- using作用类,生效!
- using在作用属性时,如果非空属性值的序列化转换,值为null,序列化不生效。需要使用nullsUsing来实现