不论你是单独序列化 List 还是将 List 作为 Organization class 的一个字段来序列化,你都可以先尝试对 List 本身进行过滤操作,然后再对过滤后得到的干净数据(即只包含 sex==male的对象)序列化。这种预先过滤数据的方法使得后续序列化过程变得更加简单,它可以避免使用到一些需要自定义 JSON serializer 行为的一些相对高级的特性,比如 fastjson 里提供的多种 filter 特性(你所提到的 ValueFilter 就是其中一种)。

下面给出预先过滤数据,然后序列化的实现方式,代码通过 Java EE 官方指定 JSON-B API 的实现(鉴于 fastjson ,jackson,Gson 的实现已经在其他回答里给出了):

Organization org = Organization.createData();
org.setPeople(org.getPeople().stream().filter(p -> "male".equals(p.getSex())).collect(Collectors.toList()));
// JSON-B for Java EEJsonbBuilder.create().toJson(org, System.out);
Console 输出结果如下:
{"orgAddress":"Hangzhou, China","orgName":"Alibaba","people":[{"name":"a","sex":"male"},{"name":"c","sex":"male"}]}

可以看到,预先过滤好数据,序列化过程使用 JSON 序列化 API 最基本属性即可完成。

仅当在如下几种情况下,我们可能无法或者不建议预先对 List 数据过滤:Organization class 没有提供 setter method:无法预先修改 Organization 的 List 字段;

List 数据量庞大,预先过滤造成不可忽视的性能开销,出于代码效率的考虑,需要将 List 的过滤操作与序列化操作结合起来进行,这就涉及到了 JSON serializer 相对高级的特性,无论使用哪种 JSON serializer,基本思路都是通过 JSON API 提供的接口,修改 serializer 的部分默认行为(比如 fastjson 的 ValueFilter)

针对上述无法预先过滤数据的情形,下面给出通过 JSON-B API 提供的 Adapter 接口来实现数据过滤与序列化结合进行的实现:

(思路说明:可以将 Adapter 看作一个 Mapper,它将不符合序列化格式的数据映射为符合我们预期的数据格式。Adapter 接口没有像 fastjson 那样细化为若干个子接口,每个子接口实现对序列化数据特定属性的修改,比如仅仅修改 value 的 ValueFilter,仅仅修改 Key 的 NameFileter,以及其他若干种 XxxFilter。JSON-B 的 Adapter 接口比较简单,它只规定映射前后输入、输出的数据类型,至于数据经由的中间映射操作,就完全由我们代码来实现)

Organization org = Organization.createData();
org.setPeople(org.getPeople().stream().filter(p -> "male".equals(p.getSex())).collect(Collectors.toList()));
JsonbConfig config = new JsonbConfig().withAdapters(new JsonbAdapter, List>() {
@Override
public List adaptToJson(List people) throws Exception {
return people.stream().filter(p -> "male".equals(p.getSex())).collect(Collectors.toList());
}
@Override
public List adaptFromJson(List obj) throws Exception {
return null; // Only needed for deserialization }
});
JsonbBuilder.create(config).toJson(org, System.out);
Console 输出结果如下:
{"orgAddress":"Hangzhou, China","orgName":"Alibaba","people":[{"name":"a","sex":"male"},{"name":"c","sex":"male"}]}
最后附上测试类和数据(就是最基本的 POJO,无需额外的注解):
public class Organization {
private String orgName;
private String orgAddress;
private List people;
public String getOrgName() {
return orgName;
}
public void setOrgName(String orgName) {
this.orgName = orgName;
}
public String getOrgAddress() {
return orgAddress;
}
public void setOrgAddress(String orgAddress) {
this.orgAddress = orgAddress;
}
public List getPeople() {
return people;
}
public void setPeople(List people) {
this.people = people;
}
public static Organization createData() {
Organization org = new Organization();
org.setOrgName("Alibaba");
org.setOrgAddress("Hangzhou, China");
org.setPeople(List.of(
new Person("a", "male"),
new Person("b", "female"),
new Person("c", "male"),
new Person("d", "female")));
return org;
}
}
public class Person {
private String name;
private String sex;
public Person(String name, String sex) {
this.name = name;
this.sex = sex;
}
public String getName() {
return name;
}
public String getSex() {
return sex;
}
public void setName(String name) {
this.name = name;
}
public void setSex(String sex) {
this.sex = sex;
}
}