Json Jackson中的过滤字段和子字段
对于某些JSON:Json Jackson中的过滤字段和子字段,json,serialization,filter,field,jackson,Json,Serialization,Filter,Field,Jackson,对于某些JSON: { "id":123, "name":"Test", "sub_object":{ "sub_field_1":1, "sub_field_2":2, "sub_field_array":[ { "array_field_1":true, "array_field_2":false }, { "array_field_1":false, "a
{
"id":123,
"name":"Test",
"sub_object":{
"sub_field_1":1,
"sub_field_2":2,
"sub_field_array":[
{
"array_field_1":true,
"array_field_2":false
},
{
"array_field_1":false,
"array_field_2":true
}
],
"sub_sub_object":{
"field_1":"me",
"field_2":"myself",
"field_3":"i",
}
}
}
我想应用一个类似于树的字段名列表。这可能用JSONPath表示:
root
|-id
|-sub_object
|-sub_field_2
|-sub_field_array
|-array_field_1
|-sub_sub_object
然后我应该得到一些类似于:
{
"id":123,
"sub_object":{
"sub_field_2":2,
"sub_field_array":[
{
"array_field_1":true
},
{
"array_field_1":false
}
],
"sub_sub_object":{
"field_1":"me",
"field_2":"myself",
"field_3":"i",
}
}
}
其思想是,对于某些字段层次结构,我想限制输出的字段
我是通过一个对其对象字段进行注释的库来实现这一点的,但我无法修改该库。如果可以,这并不重要,因为层次结构将基于每个序列化。目前,我正在将对象传递到JsonGenerator的writeObject方法中,但这会返回所有内容
某些子对象可能共享字段名,因此它不像创建SimpleBeanPropertyFilter那样简单,只序列化一组名称
提前谢谢大家,
John您可以编写一个自定义属性筛选器,该筛选器将考虑序列化属性的声明类 您应该扩展并重写
include(PropertyWriter编写器)
方法。如果给定的writer
参数是BeanPropertyWriter
类的实例,则可以提取有关属性来源的信息,并将自定义属性应用于过滤逻辑
下面是一个过滤器示例,它将排除信息存储在类及其属性名称的映射中:
public class JacksonHierarchyFilter {
@JsonFilter("filter")
public static class A {
public final String field1;
public A(final String field1) {this.field1 = field1;}
}
@JsonFilter("filter")
public static class B {
public final String field1;
public final List<A> list;
public B(final String field1, final List<A> list) {
this.field1 = field1;
this.list = list;
}
}
@JsonFilter("filter")
public static class Foo {
public final String field1;
public final List<B> field2;
public Foo(final String field1, final List<B> field2) {
this.field1 = field1;
this.field2 = field2;
}
}
public static class MyFilter extends SimpleBeanPropertyFilter {
private final Map<Class<?>, Set<String>> excludePropMap;
public MyFilter(final Map<Class<?>, Set<String>> excludePropMap) {
this.excludePropMap = excludePropMap;
}
@Override
protected boolean include(final BeanPropertyWriter writer) {
return false;
}
@Override
protected boolean include(final PropertyWriter writer) {
if (writer instanceof BeanPropertyWriter) {
final Class<?> cls = ((BeanPropertyWriter) writer).getMember().getDeclaringClass();
final Set<String> excludePropSet = excludePropMap.get(cls);
return excludePropSet == null || !excludePropSet.contains(writer.getName());
}
return true;
}
}
public static void main(String[] args) throws JsonProcessingException {
final B b = new B("B1", Arrays.asList(new A("A1"), new A("A2")));
final Foo foo = new Foo("foo", Arrays.asList(b));
final ObjectMapper mapper = new ObjectMapper();
final SimpleFilterProvider filters = new SimpleFilterProvider();
final Map<Class<?>, Set<String>> excludePropMap =
Collections.<Class<?>, Set<String>>singletonMap(
B.class,
Collections.singleton("field1"));
filters.addFilter("filter", new MyFilter(excludePropMap));
mapper.setFilters(filters);
final ObjectWriter objectWriter = mapper.writerWithDefaultPrettyPrinter();
System.out.println(objectWriter.writeValueAsString(foo));
}
}
我需要在序列化中添加一个自定义忽略注释。我的结局是
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Documented
public @interface Unsigned {}
及
ObjectMapper mapper=new ObjectMapper();
configure(SerializationConfig.Feature.SORT_PROPERTIES_字母顺序,true);
mapper.setAnnotationIntrospector(新的JacksonAnnotationIntrospector(){
@凌驾
公共字符串[]findPropertiesToIgnore(AnnotatedClass ac){
Set result=new HashSet();
对于(带注释的字段:ac.fields()){
if(field.getAnnotated().isAnnotationPresent(Unsigned.class)){
add(field.getName());
}
}
字符串[]tmp=super.findPropertiesToIgnore(ac);
如果(tmp!=null){
addAll(Arrays.asList(tmp));
}
返回result.toArray(新字符串[]{});
}
});
ObjectWriter=mapper.writer();
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Documented
public @interface Unsigned {}
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationConfig.Feature.SORT_PROPERTIES_ALPHABETICALLY, true);
mapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector() {
@Override
public String[] findPropertiesToIgnore(AnnotatedClass ac) {
Set<String> result = new HashSet<>();
for (AnnotatedField field : ac.fields()) {
if (field.getAnnotated().isAnnotationPresent(Unsigned.class)) {
result.add(field.getName());
}
}
String[] tmp = super.findPropertiesToIgnore(ac);
if (tmp != null) {
result.addAll(Arrays.asList(tmp));
}
return result.toArray(new String[] {});
}
});
ObjectWriter writer = mapper.writer();