假设我有两个简单的类
@JsonFilter("filter properties by name")
public class Foo
{
private Integer id;
private String name;
}
@JsonFilter("filter properties by name")
public class Bar
{
private Integer id;
private String name;
private Foo foo;
}
我想序列化Bar
foo
字段只有其ID的实例。这一切都应该在运行时完成。
我尝试使用过滤器
FilterProvider filter = new SimpleFilterProvider().addFilter(
"filter properties by name", SimpleBeanPropertyFilter
.serializeAllExcept(/*name of the field to exclude*/));
objectMapper.writer(filter).writeValuAsString(bar);
但是,在这样做时,我必须手动排除父类的所有字段;此外,如果此字段之一与子类的字段具有相同的名称,则它们都被排除。
在我的示例中,我无法以这种方式排除字段name
,因为它还会影响name
类的字段Bar
。
那么,我怎样才能以最简洁/优雅的方式解决? 是否有类似于上面的代码,可能使用点符号或类似的东西?
E.g。到目前为止,在我的示例过滤器中,我能够编写类似[...].serializeAllExcept("name", "foo"));
的内容,但拥有[...].serializeAllExcept("foo.name"));
或类似内容非常棒。
答案 0 :(得分:2)
您不需要任何过滤器。 Foo和Bar类没有变化。
新的MixInFoo类:
public class MixInFoo {
@JsonProperty("mixinFooId")
private Integer id;
@JsonIgnore
private String name;
}
我更改了'id'属性名称只是为了说明您可以完全更改响应而无需修改原始Foo类。
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.getSerializationConfig().addMixInAnnotations(Foo.class, MixInFoo.class);
objectMapper.getDeserializationConfig().addMixInAnnotations(Foo.class, MixInFoo.class);
String result = objectMapper.writeValueAsString(json);
您需要注册MixIn类,如图所示。
******* 基于过滤器的实施 ***********
是的,您可以使用Filter来获得相同的结果。您需要将@JsonFilter添加到Foo类并将其命名为“FooFilter”。然后,您可以添加仅适用于Foo类的Filter:
@JsonFilter("FooFilter")
public class Foo {
private Integer id;
private String name;
}
public class Bar {
private Integer id;
private String name;
private Foo foo;
}
public static void main(String []args) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
String []fooIgnore = {"name"};
SimpleBeanPropertyFilter propertyFilter = SimpleBeanPropertyFilter.serializeAllExcept(fooIgnore);
FilterProvider filterProvider = new SimpleFilterProvider().addFilter("FooFilter", propertyFilter);
ObjectWriter objectWriter = objectMapper.writer(filterProvider);
String result = objectWriter.writeValueAsString(json);
System.out.println(result);
}
在该实现中,您不需要扩展和实现自定义SimpleBeanProvider以仅将过滤器应用于Foo类。
答案 1 :(得分:1)
可以使用过滤器。您可以编写一个自定义属性过滤器,该过滤器将考虑序列化属性的声明类。
您应该扩展SimpleBeanPropertyFilter并覆盖include(PropertyWriter writer)方法。如果给定的writer参数是BeanPropertyWriter类的实例,则可以提取有关属性origin的信息并将自定义应用于过滤逻辑。
以下是一个例子:
public class JacksonParentFilter {
@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 String field2;
public B(final String field1, final String field2) {
this.field1 = field1;
this.field2 = field2;
}
}
public static class MyFilter extends SimpleBeanPropertyFilter {
private final Class<?> excludeClass;
private final Set<String> excludeProperties;
public MyFilter(final Class<?> excludeClass, final Set<String> excludeProperties) {
this.excludeClass = excludeClass;
this.excludeProperties = excludeProperties;
}
@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();
if (cls == excludeClass) {
return !excludeProperties.contains(writer.getName());
}
}
return true;
}
}
public static void main(String[] args) throws JsonProcessingException {
final A a = new A("A");
final B b = new B("B1", "B2");
final ObjectMapper mapper = new ObjectMapper();
final SimpleFilterProvider filters = new SimpleFilterProvider();
filters.addFilter("filter", new MyFilter(B.class, Collections.singleton("field1")));
mapper.setFilters(filters);
final ObjectWriter objectWriter = mapper.writerWithDefaultPrettyPrinter();
System.out.println(objectWriter.writeValueAsString(Arrays.asList(a, b)));
}
}
输出:
[ {
"field1" : "A"
}, {
"field2" : "B2"
} ]