通常在 本地存储 / 微服务 / 分布式 通讯场景下,会用到对象序列化,Serializable只是一个接口类,需要具体的对象实现它。本文主要介绍序列化时(如Fastjson、Gson、Jackson)如何实现排除指定的字段。
准备工作
当使用Fastjson添加依赖
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.79</version>
</dependency>
当使用Gson添加依赖
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.9</version>
</dependency>
当使用jackson添加依赖(注:Spring自带,可不用添加)
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.13.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.13.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.module/jackson-module-jaxb-annotations -->
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jaxb-annotations</artifactId>
<version>2.13.1</version>
</dependency>
排除指定的字段(如:name),常用方法有以下3种:
1、使用transient关键字
给需要排除的字段添加 transient 修饰符。
package com.example.demo.vo;
import java.io.Serializable;
/**
* 用户信息VO类
*
* @author 狂龙骄子
* @since 2022.01.11
*/
public class UserInfoVO implements Serializable {
private static final long serialVersionUID = 1L;
/** 用户ID */
private String uid;
/** 用户姓名 */
private transient String name;
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
测试脚本如下:
package com.example.demo.utils;
import com.alibaba.fastjson.JSON;
import com.google.gson.Gson;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import com.example.demo.vo.UserInfoVO;
/**
* 对象序列化JSON
*
* @author 狂龙骄子
* @since 2022-01-11
*/
public class test {
@Test
public void main() {
// Fastjson
UserInfoVO userInfoVO1 = new UserInfoVO();
userInfoVO1.setUid("1");
userInfoVO1.setName("admin");
System.out.println("Fastjson: " + JSON.toJSONString(userInfoVO1));
// Gson
UserInfoVO userInfoVO2 = new UserInfoVO();
userInfoVO2.setUid("1");
userInfoVO2.setName("admin");
Gson gson = new Gson();
System.out.println("Gson: " + gson.toJson(userInfoVO2));
// Jackson
UserInfoVO userInfoVO3 = new UserInfoVO();
userInfoVO3.setUid("1");
userInfoVO3.setName("admin");
try {
ObjectMapper objectMapper = new ObjectMapper();
System.out.println("jackson: " + objectMapper.writeValueAsString(userInfoVO3));
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
}
/**
输出结果如下:
Fastjson: {"uid":"1"}
Gson: {"uid":"1"}
jackson: {"uid":"1","name":"admin"}
*/
注意:Fastjson转换后的json串,是以字段名的首字排序。
2、使用注解
- Fastjson:给需要排除的字段添加 @JSONField(serialize = false) 注解
package com.example.demo.vo;
import java.io.Serializable;
import com.alibaba.fastjson.annotation.JSONField;
/**
* 用户信息VO类
*
* @author 狂龙骄子
* @since 2022.01.11
*/
public class UserInfoVO implements Serializable {
private static final long serialVersionUID = 1L;
/** 用户ID */
private String uid;
/** 用户姓名 */
@JSONField(serialize = false)
private String name;
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
- Gson:给需要序列化的字段添加@Expose注解,未添加的将被排除
package com.example.demo.vo;
import java.io.Serializable;
import com.google.gson.annotations.Expose;
/**
* 用户信息VO类
*
* @author 狂龙骄子
* @since 2022.01.11
*/
public class UserInfoVO implements Serializable {
private static final long serialVersionUID = 1L;
/** 用户ID */
@Expose
private String uid;
/** 用户姓名 */
private String name;
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
- jackson:给需要排除的字段添加 @JsonIgnore 注解
package com.example.demo.vo;
import java.io.Serializable;
import com.fasterxml.jackson.annotation.JsonIgnore;
/**
* 用户信息VO类
*
* @author 狂龙骄子
* @since 2022.01.11
*/
public class UserInfoVO implements Serializable {
private static final long serialVersionUID = 1L;
/** 用户ID */
private String uid;
/** 用户姓名 */
@JsonIgnore
private String name;
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
3、使用Filter动态排除
package com.example.demo.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SimplePropertyPreFilter;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import com.google.gson.ExclusionStrategy;
import com.google.gson.FieldAttributes;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.junit.jupiter.api.Test;
import com.example.demo.vo.UserInfoVO;
/**
* 对象序列化JSON
*
* @author 狂龙骄子
* @since 2022-01-11
*/
public class test {
@Test
public void main() {
// Fastjson
UserInfoVO userInfoVO1 = new UserInfoVO();
userInfoVO1.setUid("1");
userInfoVO1.setName("admin");
System.out.println("Fastjson: " + JSON.toJSONString(userInfoVO1));
// Fastjson 动态排除字段
SimplePropertyPreFilter excludeFilter = new SimplePropertyPreFilter();
excludeFilter.getExcludes().add("name"); // 注意:如果类包含子对象,下级同字段名的也会被排除掉
System.out.println("Fastjson(排除name): " + JSON.toJSONString(userInfoVO1, excludeFilter));
// Gson
UserInfoVO userInfoVO2 = new UserInfoVO();
userInfoVO2.setUid("1");
userInfoVO2.setName("admin");
Gson gson = new Gson();
System.out.println("Gson: " + gson.toJson(userInfoVO2));
// Gson 动态排除字段
GsonBuilder builder = new GsonBuilder();
builder.setExclusionStrategies(new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes field) {
return field.getName().equals("name");
}
@Override
public boolean shouldSkipClass(Class<?> aClass) {
return false;
}
});
gson = builder.create();
System.out.println("Gson(排除name): " + gson.toJson(userInfoVO2));
// Jackson
UserInfoVO userInfoVO3 = new UserInfoVO();
userInfoVO3.setUid("1");
userInfoVO3.setName("admin");
try {
ObjectMapper objectMapper = new ObjectMapper();
// 使用动态排除,必须先添加 FilterProvider(),否则直接转JSON串会抛调用异常
//System.out.println("jackson: " + objectMapper.writeValueAsString(userInfoVO3));
// Jackson 动态排除字段
String[] beanProperties = new String[]{"name"};
// TODO 需要在类上,额外添加 @JsonFilter() 注解
String nonFilterName = "non-name";
SimpleFilterProvider simpleFilterProvider = new SimpleFilterProvider()
.addFilter(nonFilterName, SimpleBeanPropertyFilter.serializeAllExcept(beanProperties));
objectMapper.setFilterProvider(simpleFilterProvider);
System.out.println("jackson(排除name): " + objectMapper.writeValueAsString(userInfoVO3));
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
}
/**
输出结果如下:
Fastjson: {"name":"admin","uid":"1"}
Fastjson(排除name): {"uid":"1"}
Gson: {"uid":"1","name":"admin"}
Gson(排除name): {"uid":"1"}
jackson(排除name): {"uid":"1"}
*/
通过对比发现,Fastjson 在排除指定字段时,无论是注解、调用方式,更简洁些。
如果有未提及的技巧,欢迎留言讨论,谢谢……