名词解释:
- 序列化:将对象转换为 JSON 字符串
- 反序列化:将 JSON 字符串转换为对象
一、@JsonIgnore:
- 作用: 在json序列化时将java bean中的一些属性忽略掉,序列化和反序列化都受影响。一般标记在属性或者方法上,在返回的json数据就不包含该属性。
- 场景模拟: 将一个User序列化成Json数据并返回给前台,当我们在User的password和email属性上添加@JsonIgnore注解时,即使后台给这两个属性赋值了,返回前台的Json也不包含它们。
- 首先在pom.xml中添加依赖
<dependencies>
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-core</artifactId>
<version>1.0.4</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.6</version>
</dependency>
</dependencies>
- 创建实体类
public class User {
private String name;
private String age;
private String sex;
@JsonIgnore //添加JsonIgnore注解,返回时被忽略
private String password;
@JsonIgnore //添加JsonIgnore注解,返回时被忽略
private String email;
public User() {}
}
@JsonIgnore
注解失效 如果注解失效,可能是因为你使用的是fastJson
,尝试使用对应的注解来忽略字段,注解为:@JSONField(serialize = false)
,使用方法一样。- 补充:
jackSon
中@JsonIgnore
,@JsonIgnoreProperties
and@JsonIgnoreType
注解使用详解
这个注解是用在字段上,get或者set方法上,效果都是一样的,用来在实体类序列化和反序列化的时候忽略该字段字段。
二、@JsonIgnoreProperties
1、概念:
是类注解,作用是json序列化时将java bean中的一些属性忽略掉,序列化和反序列化都受影响。
2、用法:
@JsonIgnoreProperties(ignoreUnknown = true),将这个注解写在类上之后,就会忽略类中不存在的字段。
这个注解和@JsonIgnore注解功能是一样的,区别就是这个注解是用在类上面的,在需要的注解比较多的情况下,用来一次性定义忽略的字段如:
代码语言:java复制@Data
@JsonIgnoreProperties(value = {"fullName", "comment"})
public class User {
private String id;
private String name;
private String fullName;
private String comment;
private String mail;
@JsonIgnore
private String address;
@JsonFormat(timezone = "GMT 8", pattern = "yyyy-MM-dd HH:mm:ss")
private Date regDate;
private Date reg2Date;
}
说明:User类的fullName
和comment
字段会被@JsonIgnoreProperties
注解忽略。address
字段会被@JsonIgnore
注解忽略。regDate
会按照@JsonFormat(timezone = “GMT 8”, pattern = “yyyy-MM-dd HH:mm:ss”)
进行格式转。
controller示例代码:
代码语言:java复制@ApiOperation(value = "按用户id删除", notes="private")
@ApiImplicitParams({@ApiImplicitParam(name = "userId", defaultValue = "2", value = "userID", required = true, dataType = "string", paramType = "path"),})
@DeleteMapping(value = "/users/{userId}", produces = "application/json;charset=UTF-8")
public User delUser(@PathVariable String userId) {
User user = (User)userSvc.deleteById(userId);
log.info("rest del user={} by id={}", user, userId);
return user;
}
可以看到返回的对象是User,然后comment、fullName、address属性被忽略了,regDate的格式进行转换。
三、@JsonFormat
- 作用:
- Date和String的相互转化
- 时差调整
- 使用场景
- 一般后台传值给前台时
- 在我们中国来讲和我们的北京时间,会相差8个小时,因为我们是东八区(北京时间)。所以我们在格式化的时候要指定时区(timezone )
Date和String的自动转化
代码语言:java复制 import com.fasterxml.jackson.annotation.JsonFormat;
/**
* 后台返给前台时, 日期自动格式化
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date birth;
指定时区:
代码语言:java复制/**更新时间 用户可以点击更新,保存最新更新的时间。**/
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT 8")
private Date updateTime;
四、@JsonInclude
在将 java pojo 对象序列化成为 json 字符串时,使用 @JsonInclude
注解可以控制在哪些情况下才将被注解的属性转换成 json,例如只有属性不为 null 时。
@JsonInclude(JsonInclude.Include.NON_NULL) //类前面使用,如果为空则不反悔该属性json
public class SellerInfoEntity {
private String id;
private String username;
@JsonInclude(JsonInclude.Include.NON_EMPTY) //属性前使用,如果为空则不返回该属性json
private String password;
private String openid;
private Timestamp createTime;
private Timestamp updateTime;
public SellerInfoEntity() {
}
public SellerInfoEntity(String id, String username, String password, String openid) {
this.id = id;
this.username = username;
this.password = password;
this.openid = openid;
}
}
五、@JsonSerialize
@JsonSerialize
是 Jackson
库中的一个注解,用于指定在将 Java 对象序列化为 JSON 格式时,如何进行自定义的序列化处理。
通过这个注解,指定一个自定义的序列化器(serializer),以控制对象的序列化过程。
代码语言:java复制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> 需要实现以下方法:
代码语言:java复制serialize(T value, JsonGenerator gen, SerializerProvider serializers):
该方法定义了如何将对象 value 序列化为 JSON 格式,并使用 JsonGenerator 对象进行输出。
常使用的using以及nullsUsing
JsonSerialize 注解
: 用于指定自定义序列化器的注解。JsonSerializer 接口
: 自定义序列化器需要实现这个接口,然后通过@JsonSerialize
注解的using
属性指定使用哪个序列化器。
该注解可以应用在类中,也可应用在属性中,对类的不同属性使用不同的序列化逻辑,从而更加灵活地控制 JSON 序列化的过程。
除了using的注解也还有nullsUsing 等注解,@JsonSerialize(nullsUsing = xx.class) 的含义是,当某个属性的值为 null 时,使用指定的自定义序列化器 xx.class 来处理该属性的序列化。
nullsUsing
: 该属性用于指定在属性值为 null 时使用的序列化器。xx.class
: 自定义的序列化器类,它实现了 Jackson 的 JsonSerializer 接口,定义了处理 null 值的序列化逻辑。
代码如下:
代码语言:java复制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"
。
总的来说,其作用如下:
- 定制化需求: 继承可以提供更大的灵活性,允许开发者完全控制序列化过程。
- 特定类型处理: 可以为不同类型的对象创建不同的序列化逻辑,以满足特定的业务需求。
- 重用性: 可以将自定义序列化器用于多个类,提高代码的重用性。
案例:
假设有一个包含日期信息的类 CustomDate,并且将其序列化为 JSON 格式时,按照特定的格式输出日期。
通过继承 JsonSerializer<T> 来实现自定义的日期序列化逻辑。
注意看两个Demo的区分,分别应用在类或者属性上,以及使用using或者nullsUsing的区别!
5.1 jsontest1
注解应用在类上,且属性都会被序列化为某个特性:
对于序列化的方式如下:
代码语言:java复制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);
}
}
截图如下:
5.2 jsontest2
对应序列化的类如下:(序列化的值为空!)
代码语言:java复制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("");
}
}
其运行的主函数如下:(注意传输的值为空!)
代码语言:java复制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);
}
}
如果代码为如下:
代码语言:java复制class CustomDate {
@JsonSerialize(using = CustomDateSerializer.class)
private Date date;
public CustomDate(){}
public CustomDate(Date date) {
this.date = date;
}
public Date getDate() {
return date;
}
}
输出结果为:(这说明序列化失败),但注意如果这样放在类上,是可以成功的!
为了在属性上可以序列化,应该使用如下方式:
代码语言:java复制class CustomDate {
@JsonSerialize(nullsUsing = CustomDateSerializer.class)
private Date date;
public CustomDate(){}
public CustomDate(Date date) {
this.date = date;
}
public Date getDate() {
return date;
}
}
截图如下所示:
对应的将该注解放在类上,序列化可以成功!
六、@JsonDeserialize用法
@JsonDeserialize
可以在对象反序列化时执行自定义的代码,我们利用这个特性可以针对对象某个属性进行特性的处理。将特定格式的日期时间反序列化成LocalDateTime对象
属性
代码语言:java复制@JsonDeserialize(using = LocalDateTimeFormmatDeserializa.class)
private LocalDateTime planInDate;
反序列化器
代码语言:java复制import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class LocalDateTimeFormmatDeserializa extends JsonDeserializer<LocalDateTime> {
@Override
public LocalDateTime deserialize(JsonParser p, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
JsonNode node = p.getCodec().readTree(p);
// 之所以是用"yyyy-MM-dd'T'HH:mm:ss"这个格式解析成对象,是因为json字符串字段格式这样的
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
LocalDateTime parse = LocalDateTime.parse(node.asText(), formatter);
return parse;
}
}