对于某些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,
"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来仅序列化一组名称那么简单。
提前谢谢你,
约翰
答案 0 :(得分:1)
您可以编写自定义属性过滤器,该过滤器将考虑序列化属性的声明类。
您应该扩展SimpleBeanPropertyFilter并覆盖include(PropertyWriter writer)
方法。如果给定的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));
}
}
输出:
{
"field1" : "foo",
"field2" : [ {
"list" : [ {
"field1" : "A1"
}, {
"field1" : "A2"
} ]
} ]
}
答案 1 :(得分:0)
我需要在序列化中添加自定义忽略注释。我最终得到的是
@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();