Serialization jackson自定义序列化和筛选

Serialization jackson自定义序列化和筛选,serialization,jackson,Serialization,Jackson,我需要在Jackson中自定义POJO的序列化,以便根据用户输入对属性应用过滤器 我在POJO上应用了以下注释 @JsonFilter("userFilter") @JsonSerialize(using = UserSerializer.class) 自定义序列化程序类如下所示 public class UserSerializer extends JsonSerializer<User> { @Override public void serialize(

我需要在Jackson中自定义POJO的序列化,以便根据用户输入对属性应用过滤器

我在POJO上应用了以下注释

@JsonFilter("userFilter")
@JsonSerialize(using = UserSerializer.class)
自定义序列化程序类如下所示

public class UserSerializer  extends JsonSerializer<User> {


    @Override
    public void serialize(User value, JsonGenerator jgen,
            SerializerProvider provider) throws IOException,
            JsonProcessingException {

        ObjectMapper mapper = new ObjectMapper();
        SimpleFilterProvider sfp = new SimpleFilterProvider();

        // create a  set that holds name of User properties that must be serialized
        Set userFilterSet = new HashSet<String>();
        userFilterSet.add("firstName");
        userFilterSet.add("corporateOrgs");
        userFilterSet.add("rights");
        userFilterSet.add("requirements");


        sfp.addFilter("userFilter",SimpleBeanPropertyFilter.filterOutAllExcept(userFilterSet));

        // create an objectwriter which will apply the filters 
        ObjectWriter writer = mapper.writer(sfp);

        String json = writer.writeValueAsString(value);


    }

}
公共类UserSerializer扩展JsonSerializer{
@凌驾
public void序列化(用户值,JsonGenerator jgen,
SerializerProvider提供程序)引发IOException,
JsonProcessingException{
ObjectMapper mapper=新的ObjectMapper();
SimpleFilterProvider sfp=新的SimpleFilterProvider();
//创建一个包含必须序列化的用户属性名称的集
Set userFilterSet=newhashset();
userFilterSet.add(“firstName”);
userFilterSet.add(“公司组织”);
userFilterSet.add(“权利”);
用户过滤器集添加(“要求”);
addFilter(“userFilter”,SimpleBeanPropertyFilter.FilterOutalExcept(userFilterSet));
//创建将应用过滤器的objectwriter
ObjectWriter=mapper.writer(sfp);
字符串json=writer.writeValueAsString(值);
}
}
我可以看到Jackson正在尝试使用定义的自定义序列化程序序列化POJO。但是,它以无限递归/stackoverflow结束,因为
writer.writeValueAsString(value)
再次调用自定义序列化程序

显然,我这里没有一些基本的东西。如果过滤是在serialize方法之外完成的(例如,在从
main()
调用的方法中),则过滤工作正常


任何人都可以提供有关如何使用自定义序列化来利用筛选的文档的详细信息/链接。

可以使用JsonFilter筛选出字段,或者您可以创建一个只写出特定字段的自定义JsonSerialize序列化器

与JsonFilter的使用无关,在带有对象映射器的用户定义序列化程序中,尝试递归地重新序列化要序列化的同一对象(Overwrited
serialize
方法的第一个参数)将导致无限循环。相反,在自定义序列化程序中,您更希望使用JsonGenerator方法(重写的
serialize
方法的第二个参数)写出字段名/值

在下面的回答中,演示了两个变量(@JsonFilter和@JsonSerialize),其中只有一部分可用字段被序列化为JSON

@JsonFilter

要根据用户输入将过滤器应用于属性,不需要扩展JsonSerializer。相反,您可以使用JsonFilter注释POJO,然后只应用过滤

基于您的代码的自包含示例如下所示:

package com.software7.test;

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 java.util.HashSet;
import java.util.Set;

public class Main {

    public static void main(String[] args) {
        Main m = new Main();
        try {
            m.serialize();
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }

    void serialize() throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        SimpleFilterProvider sfp = new SimpleFilterProvider();

        Set<String> userFilterSet = new HashSet<>();
        userFilterSet.add("firstName");
        userFilterSet.add("corporateOrgs");
        userFilterSet.add("rights");
        userFilterSet.add("requirements");

        sfp.addFilter("UserFilter",
                SimpleBeanPropertyFilter.filterOutAllExcept(userFilterSet));

        mapper.setFilterProvider(sfp);

        User user = new User("Brownrigg", "Don", "none", "+rwx", "n/a",
                "some", "superfluous", "properties");
        System.out.println(user);
        System.out.println(">>>> serializing >>>>");
        String s = mapper.writeValueAsString(user);
        System.out.println(s);
    }
}
User{lastName='Brownrigg', firstName='Don', corporateOrgs='none', rights='+rwx', requirements='n/a', a='some', b='superfluous', c='properties'}
>>>> serializing >>>>
{"firstName":"Don","corporateOrgs":"none","rights":"+rwx","requirements":"n/a"}
package com.software7.test;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;

import java.io.IOException;

public class UserSerializer extends JsonSerializer<User> {
    @Override
    public void serialize(User user, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
            throws IOException, JsonProcessingException {
        jsonGenerator.writeStartObject();
        jsonGenerator.writeObjectField("firstName", user.firstName);
        jsonGenerator.writeObjectField("corporateOrgs", user.corporateOrgs);
        jsonGenerator.writeObjectField("rights", user.rights);
        jsonGenerator.writeObjectField("requirements", user.requirements);
        jsonGenerator.writeEndObject();
    }
}
void serialize() throws JsonProcessingException {
    ObjectMapper mapper = new ObjectMapper();

    User user = new User("Brownrigg", "Don", "none", "+rwx", "n/a",
            "some", "superfluous", "properties");
    System.out.println(user);
    System.out.println(">>>> serializing >>>>");
    String s = mapper.writeValueAsString(user);
    System.out.println(s);
}
测试

上述程序的调试输出如下所示:

package com.software7.test;

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 java.util.HashSet;
import java.util.Set;

public class Main {

    public static void main(String[] args) {
        Main m = new Main();
        try {
            m.serialize();
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }

    void serialize() throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        SimpleFilterProvider sfp = new SimpleFilterProvider();

        Set<String> userFilterSet = new HashSet<>();
        userFilterSet.add("firstName");
        userFilterSet.add("corporateOrgs");
        userFilterSet.add("rights");
        userFilterSet.add("requirements");

        sfp.addFilter("UserFilter",
                SimpleBeanPropertyFilter.filterOutAllExcept(userFilterSet));

        mapper.setFilterProvider(sfp);

        User user = new User("Brownrigg", "Don", "none", "+rwx", "n/a",
                "some", "superfluous", "properties");
        System.out.println(user);
        System.out.println(">>>> serializing >>>>");
        String s = mapper.writeValueAsString(user);
        System.out.println(s);
    }
}
User{lastName='Brownrigg', firstName='Don', corporateOrgs='none', rights='+rwx', requirements='n/a', a='some', b='superfluous', c='properties'}
>>>> serializing >>>>
{"firstName":"Don","corporateOrgs":"none","rights":"+rwx","requirements":"n/a"}
package com.software7.test;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;

import java.io.IOException;

public class UserSerializer extends JsonSerializer<User> {
    @Override
    public void serialize(User user, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
            throws IOException, JsonProcessingException {
        jsonGenerator.writeStartObject();
        jsonGenerator.writeObjectField("firstName", user.firstName);
        jsonGenerator.writeObjectField("corporateOrgs", user.corporateOrgs);
        jsonGenerator.writeObjectField("rights", user.rights);
        jsonGenerator.writeObjectField("requirements", user.requirements);
        jsonGenerator.writeEndObject();
    }
}
void serialize() throws JsonProcessingException {
    ObjectMapper mapper = new ObjectMapper();

    User user = new User("Brownrigg", "Don", "none", "+rwx", "n/a",
            "some", "superfluous", "properties");
    System.out.println(user);
    System.out.println(">>>> serializing >>>>");
    String s = mapper.writeValueAsString(user);
    System.out.println(s);
}
测试成功了!如您所见,属性
lastName
a
b
c
被删除

@json系列化备选方案

如果您想改用客户序列化程序,可以这样做:

替换注释:

@JsonFilter("UserFilter")

但不要两者都用

UserSerializer类可以如下所示:

package com.software7.test;

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 java.util.HashSet;
import java.util.Set;

public class Main {

    public static void main(String[] args) {
        Main m = new Main();
        try {
            m.serialize();
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }

    void serialize() throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        SimpleFilterProvider sfp = new SimpleFilterProvider();

        Set<String> userFilterSet = new HashSet<>();
        userFilterSet.add("firstName");
        userFilterSet.add("corporateOrgs");
        userFilterSet.add("rights");
        userFilterSet.add("requirements");

        sfp.addFilter("UserFilter",
                SimpleBeanPropertyFilter.filterOutAllExcept(userFilterSet));

        mapper.setFilterProvider(sfp);

        User user = new User("Brownrigg", "Don", "none", "+rwx", "n/a",
                "some", "superfluous", "properties");
        System.out.println(user);
        System.out.println(">>>> serializing >>>>");
        String s = mapper.writeValueAsString(user);
        System.out.println(s);
    }
}
User{lastName='Brownrigg', firstName='Don', corporateOrgs='none', rights='+rwx', requirements='n/a', a='some', b='superfluous', c='properties'}
>>>> serializing >>>>
{"firstName":"Don","corporateOrgs":"none","rights":"+rwx","requirements":"n/a"}
package com.software7.test;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;

import java.io.IOException;

public class UserSerializer extends JsonSerializer<User> {
    @Override
    public void serialize(User user, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
            throws IOException, JsonProcessingException {
        jsonGenerator.writeStartObject();
        jsonGenerator.writeObjectField("firstName", user.firstName);
        jsonGenerator.writeObjectField("corporateOrgs", user.corporateOrgs);
        jsonGenerator.writeObjectField("rights", user.rights);
        jsonGenerator.writeObjectField("requirements", user.requirements);
        jsonGenerator.writeEndObject();
    }
}
void serialize() throws JsonProcessingException {
    ObjectMapper mapper = new ObjectMapper();

    User user = new User("Brownrigg", "Don", "none", "+rwx", "n/a",
            "some", "superfluous", "properties");
    System.out.println(user);
    System.out.println(">>>> serializing >>>>");
    String s = mapper.writeValueAsString(user);
    System.out.println(s);
}

在本例中,结果是相同的。哪种变体更合适取决于具体的用例或个人偏好。

非常感谢您提供的详细答案。我在使用/@JsonFilter时遇到了类似“InvalidDefinitionException:无法解析id为的PropertyFilter”的错误,但现在我可以从您的示例中运行/@JsonFilter和/@JsonSerialize。