全面总结Fastjson过滤字段、排除字段的5种方法(含示例)

6,413 阅读4分钟

1.通过注解指定不需要序列化的字段

在不需要序列化的字段,添加@JSONField(serialize = false)注解可进行排除。

public class DontSerializeAnnotation {

	@JSONField(serialize = false)
    private Long id;
    private String name;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

/**
 * 通过注解指定不需要序列化的字段:@JSONField(serialize = false)
 */
@Test
public void testDontSerializeAnnotation() {
	DontSerializeAnnotation guestUser = new DontSerializeAnnotation();
	guestUser.setId(2L);
	guestUser.setName("guest");
	System.out.println(JSON.toJSONString(guestUser));
}

执行结果:

{"name":"guest"}

2.声明为transient的变量不进行序列化

如果被序列化的字段使用transient修饰,则不会被序列化。

public class TransientObject {

    private Long id;
    private transient String name;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

/**
 * 声明为transient的变量不进行序列化
 */
@Test
public void testTransientObject() {
	TransientObject guestUser = new TransientObject();
	guestUser.setId(2L);
	guestUser.setName("guest");
	System.out.println(JSON.toJSONString(guestUser));
}

执行结果:

{"id":2}

3.使用属性过滤器排除不需要序列化的字段

使用过滤器SimplePropertyPreFilter,可以一次性设置1到多个需要过滤掉的字段。

3.1 过滤对象中的某个字段

public class User {

    private Long id;
    private String name;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

/**
 * 使用属性过滤器排除不需要序列化的字段
 */
@Test
public void testExcludeSingleFilter() {
	User guestUser = new User();
	guestUser.setId(2L);
	guestUser.setName("guest");
	
	SimplePropertyPreFilter filter = new SimplePropertyPreFilter();
	filter.getExcludes().add("name"); // 排除字段名为name的字段
	
	System.out.println(JSON.toJSONString(guestUser, filter));
}

执行结果:

{"id":2}

3.2 过滤嵌套类中的相同名字的字段

Group中的User,参照上一小节。

public class Group {

    private Long id;
    private String name;
    private List<User> users = new ArrayList<User>();

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<User> getUsers() {
        return users;
    }

    public void setUsers(List<User> users) {
        this.users = users;
    }

    public void addUser(User user) {
        users.add(user);
    }
}

/**
 * 使用属性过滤器排除不需要序列化的字段.
 * 对于嵌套多层的类,不同类中具有相同名称的字段都会被过滤掉。
 */
@Test
public void testExcludeEmbedFilter() {
	Group group = new Group();
	group.setId(0L);
	group.setName("admin");

	User guestUser = new User();
	guestUser.setId(2L);
	guestUser.setName("guest");

	User rootUser = new User();
	rootUser.setId(3L);
	rootUser.setName("root");

	group.addUser(guestUser);
	group.addUser(rootUser);

	SimplePropertyPreFilter filter = new SimplePropertyPreFilter();
	filter.getExcludes().add("name");
	
	System.out.println(JSON.toJSONString(group, filter));
}

执行结果:

{"id":0,"users":[{"id":2},{"id":3}]}

3.3 使用多个属性过滤器排除不需要序列化的字段

如果只想过滤特定类中的字段,可以在创建过滤器的时候,指定对应类的class对象和字段。

下面示例,分别对Group和User创建一个过滤器,过滤掉不同的字段。

/**
 * 使用多个属性过滤器排除不需要序列化的字段.
 */
@Test
public void testExcludeMultiFilter() {
	Group group = new Group();
	group.setId(0L);
	group.setName("admin");
	
	User guestUser = new User();
	guestUser.setId(2L);
	guestUser.setName("guest");
	
	User rootUser = new User();
	rootUser.setId(3L);
	rootUser.setName("root");
	
	group.addUser(guestUser);
	group.addUser(rootUser);
	
	// Group的过滤器,过滤掉id字段
	SimplePropertyPreFilter filter1 = new SimplePropertyPreFilter(Group.class);
	filter1.getExcludes().add("id");
	// User的过滤器,过滤掉name字段
	SimplePropertyPreFilter filter2 = new SimplePropertyPreFilter(User.class);
	filter2.getExcludes().add("name");
	
	System.out.println(JSON.toJSONString(group, new SimplePropertyPreFilter[] {filter1, filter2}));
}

执行结果:

{"name":"admin","users":[{"id":2},{"id":3}]}

4.使用属性过滤器包含需要序列化的字段.

有些时候,我们仅仅需要序列化个别字段,或者当需要排除的字段比序列化的字段还要多的时候,这时可以使用包含而非排除的过滤器。

/**
 * 使用属性过滤器包含需要序列化的字段.
 */
@Test
public void testIncludeMultiFilter() {
	Group group = new Group();
	group.setId(0L);
	group.setName("admin");
	
	User guestUser = new User();
	guestUser.setId(2L);
	guestUser.setName("guest");
	
	User rootUser = new User();
	rootUser.setId(3L);
	rootUser.setName("root");
	
	group.addUser(guestUser);
	group.addUser(rootUser);
	
	// Group只序列化id和users
	SimplePropertyPreFilter filter1 = new SimplePropertyPreFilter(Group.class, "id", "users");
	// User只序列化name
	SimplePropertyPreFilter filter2 = new SimplePropertyPreFilter(User.class);
	filter2.getIncludes().add("name");
	
	System.out.println(JSON.toJSONString(group, new SimplePropertyPreFilter[] {filter1, filter2}));
}

执行结果:

{"id":0,"users":[{"name":"guest"},{"name":"root"}]}

5.自定义属性过滤规则

在某些特殊的场景下,以上简单的排除或包含方式,并不能很好的满足实际的应用需求。

这时,可以考虑通过自定义属性过滤器,来实现过滤。这种实现方式非常灵活,可以根据实际的需求进行实现。

可以对类、字段名和字段值执行某种规则判断,来决定是否需要进行序列化。

具体方法,是实现PropertyFilter接口中的apply方法,返回true表示包含该字段,返回false表示过滤掉。

/**
 * @author wenshao[szujobs@hotmail.com]
 */
public interface PropertyFilter extends SerializeFilter {

    /**
     * @param object the owner of the property. 字段所属的对象
     * @param name the name of the property. 字段名
     * @param value the value of the property. 字段值
     * @return true if the property will be included, false if to be filtered out
     */
    boolean apply(Object object, String name, Object value);
}
/**
 * 自定义属性过滤规则,最灵活的一种实现字段和值过滤的方式。
 */
@Test
public void testPropertyFilter() {
	Group group = new Group();
	group.setId(0L);
	group.setName("admin");
	
	User guestUser = new User();
	guestUser.setId(2L);
	guestUser.setName("guest");
	
	User rootUser = new User();
	rootUser.setId(3L);
	rootUser.setName("root");
	
	group.addUser(guestUser);
	group.addUser(rootUser);
	
	PropertyFilter filter = new PropertyFilter() {
        @Override
        public boolean apply(Object object, String name, Object value) {
        	//System.out.println(object + " " + name + " " + value);
            if (name.equals("name")) {
                return false; // 排除名为name的字段
            }
            if (value.toString().equals("2")) {
            	return false; // 排除值为2的字段
            }
            return true; // 包含该字段或值
        }
    };
    
    System.out.println(JSON.toJSONString(group, filter));
}

执行结果:

{"id":0,"users":[{},{"id":3}]}

---转载本站文章请注明作者和出处 二进制之路(binarylife.icu),请勿用于任何商业用途---

个人博客:binarylife.icu/

公众号:二进制之路

二进制之路