通常在 本地存储 微服务 分布式 通讯场景下,会用到对象序列化,Serializable只是一个接口类,需要具体的对象实现它。本文主要介绍序列化时(如FastjsonGson、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 在排除指定字段时,无论是注解、调用方式,更简洁些。

如果有未提及的技巧,欢迎留言讨论,谢谢……

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐