serialization - jackson 自定义序列化与过滤

标签 serialization jackson

我需要在 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);


    }

}

我可以看到 Jackson 正在尝试使用定义的自定义序列化程序序列化 POJO。然而,它最终以无限递归/计算器溢出为 writer.writeValueAsString(value)最终再次调用自定义序列化程序。

显然,我在这里没有得到一些基本的东西。如果过滤是在序列化方法之外完成的(例如在从 main() 调用的方法中),过滤会按预期工作。

任何人都可以提供有关如何使用自定义序列化来利用过滤的文档的见解/链接。

最佳答案

可以使用 JsonFilter 过滤掉字段,或者您可以创建一个自定义的 JsonSerialize 序列化程序,它只写出某些字段。
独立于 JsonFilter 的使用,尝试在具有对象映射器的用户定义序列化器中递归地重新序列化要序列化的同一对象(覆盖 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);
    }
}
用户POJO
package com.software7.test;

import com.fasterxml.jackson.annotation.JsonFilter;

@JsonFilter("UserFilter")
public class User {
    public String lastName;
    public String firstName;
    public String corporateOrgs;
    public String rights;
    public String requirements;
    public String a, b, c;

    public User(String lastName, String firstName, String corporateOrgs, String rights, String requirements,
                String a, String b, String c) {
        this.lastName = lastName;
        this.firstName = firstName;
        this.corporateOrgs = corporateOrgs;
        this.rights = rights;
        this.requirements = requirements;
        this.a = a;
        this.b = b;
        this.c = c;
    }

    @Override
    public String toString() {
        return "User{" +
                "lastName='" + lastName + '\'' +
                ", firstName='" + firstName + '\'' +
                ", corporateOrgs='" + corporateOrgs + '\'' +
                ", rights='" + rights + '\'' +
                ", requirements='" + requirements + '\'' +
                ", a='" + a + '\'' +
                ", b='" + b + '\'' +
                ", c='" + c + '\'' +
                '}';
    }
}
测试
上述程序的调试输出如下所示:
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"}
测试成功!如您所见,属性 lastName , a , bc被删除。
@JsonSerialize 替代方案
如果您想使用客户序列化程序,您可以这样做:
替换注释:
@JsonFilter("UserFilter")
@JsonSerialize(using = UserSerializer.class)
但不要同时使用。
UserSerializer 类可能如下所示:
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);
}
在这个例子中结果是一样的。哪种变体更适合取决于特定用例或个人偏好。

关于serialization - jackson 自定义序列化与过滤,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22929318/

相关文章:

php - 是否可以使用 JMS Serializer 将数组序列化到对象的根?

c# - Newtonsoft 反序列化向列表添加空值

Java 序列化与继承?

java - Spring中的自定义json

kotlin - 使用Jackson使用模式反序列化Property

jaxb - Jersey 通过 JAXB 解码 JSON 时的空处理?

java - 将 HttpClient 对象从一个 Activity 传递到另一个 Activity

c# - 如何将任何类型的文件转换为字节数组?

Java JsonNode 删除中间一个容器

java - Jackson:反序列化和序列化后如何检测修改后的对象?