0

我正在实现 RESTful API,我希望调用者指定一个喜欢被序列化的特定属性,例如/dogs/1?fields=name,breed. 因此,如果狗除了名称和品种之外还有更多属性,并且我正在使用像杰克逊这样的标准序列化库,我怎么能告诉杰克逊在运行时序列化时忽略其余属性?

换句话说,告诉杰克逊在运行时动态忽略某些属性的方法是什么?

4

2 回答 2

3

您没有指定 Jackson 库的版本,所以我假设您使用的是 2.2.0 或最新版本。在杰克逊,这不是一件容易的事,但我们可以做到,例如,使用BasicClassIntrospector。下面的源代码显示了它的外观。例如我们有一个 POJO 类:

class User {

    private String name;
    private String surname;

    // getters/setters
}

我们必须定义新的 BasicClassIntrospector,它只返回 bean 定义对象,其中包含我们需要的这些字段:

class ExclusionAnnotationIntrospector extends BasicClassIntrospector {

    private Collection<String> properties;

    public ExclusionAnnotationIntrospector(Collection<String> properties) {
        this.properties = properties;
    }

    @Override
    public BasicBeanDescription forSerialization(SerializationConfig serializationConfig,
            JavaType javaType, MixInResolver mixInResolver) {

        BasicBeanDescription beanDesc = super.forSerialization(serializationConfig, javaType,
                mixInResolver);
        deleteUnwantedProperties(beanDesc);

        return beanDesc;
    }

    private void deleteUnwantedProperties(BasicBeanDescription beanDesc) {
        List<BeanPropertyDefinition> beanProperties = new ArrayList<BeanPropertyDefinition>(
                beanDesc.findProperties());
        for (BeanPropertyDefinition bpd : beanProperties) {
            String name = bpd.getName();
            if (!properties.contains(name)) {
                beanDesc.removeProperty(name);
            }
        }
    }
}

现在,我们必须使用上述自省器创建新的 ObjectMapper 类。我们必须在构造函数中定义我们需要的属性:

class CustomObjectMapper extends ObjectMapper {

    public CustomObjectMapper(Collection<String> properties) {
        this._serializationConfig = getSerializationConfig().with(
                new ExclusionAnnotationIntrospector(properties));
    }
}

最后,示例用法:

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.introspect.BasicBeanDescription;
import com.fasterxml.jackson.databind.introspect.BasicClassIntrospector;
import com.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;

public class JacksonProgram {

    public static void main(String[] args) throws Exception {
        User user = new User();
        user.setName("Tom");
        user.setSurname("Garnier");

        CustomObjectMapper onlyNameSerializer = new CustomObjectMapper(toSet("name"));
        CustomObjectMapper onlySurnameSerializer = new CustomObjectMapper(toSet("surname"));
        CustomObjectMapper fullUserSerializer = new CustomObjectMapper(toSet("name", "surname"));

        System.out.println(onlyNameSerializer.writeValueAsString(user));
        System.out.println(onlySurnameSerializer.writeValueAsString(user));
        System.out.println(fullUserSerializer.writeValueAsString(user));
    }

    private static Set<String> toSet(String... params) {
        HashSet<String> set = new HashSet<String>();
        for (String item : params) {
            set.add(item);
        }

        return set;
    }
}

上面的程序打印:

{"name":"Tom"}
{"surname":"Garnier"}
{"name":"Tom","surname":"Garnier"}
于 2013-09-03T00:20:10.207 回答
0

我建议看看http://flexjson.sourceforge.net/ (特别是使用 Includes/Excludes部分)

例子:

    public String toJsonWithIncludes(Object obj, String...includes) {
            return new JSONSerializer()
                    .include(includes)
                    .exclude("data.*","*.class")
                    .serialize(obj);
    }

...
toJsonWithIncludes(obj, "name","breed");
于 2017-09-19T21:47:27.187 回答