简体   繁体   中英

Jackson ignore fields by name outside a subtree

I have a class structure like below (a simplified version):

public class A {
    public int a;
    public B b;
    public C c;
    public D d;
    public E e;
}

public class B {
    public int a;
}

public class C {
    public int a;
    public D d;
}

public class D {
    public int a;
}

public class E {
    public int a;
}

While serializing A , I'd like to remove a fields for all classes except the classes included under the C subtree. Which means I'd like to keep a fields in C instance and D instance (but only for the one under C ). I hope I was clear.

I tried to use MixIns or provide custom serializers but couldn't achieve what I want.

Note that in reality there are too many classes including the a field and the classes being serialized are auto-generated.

Use JsonFilter annotation on a field. You can register it via MixIn feature and enable on given type and getter methods. See below code:

import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;

public class JsonApp {

    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        mapper.enable(SerializationFeature.INDENT_OUTPUT);
        mapper.addMixIn(A.class, AMixIn.class);

        SimpleFilterProvider filterProvider = new SimpleFilterProvider()
            .addFilter("excludeA", SimpleBeanPropertyFilter.serializeAllExcept("a"));

        mapper.setFilterProvider(filterProvider);

        System.out.println(mapper.writeValueAsString(new A()));
    }
}

@JsonFilter("excludeA")
interface AMixIn {

    @JsonFilter("excludeA")
    B getB();

    @JsonFilter("excludeA")
    D getD();

    @JsonFilter("excludeA")
    E getE();
}

For your POJO model above code prints:

{
  "b" : { },
  "c" : {
    "a" : 3,
    "d" : {
      "a" : 4
    }
  },
  "d" : { },
  "e" : { }
}

See also:

I was able to solve the problem as follows thanks to the hint @Michał Ziober provided:

// custom serializer for C class, which in fact serializes all fields
public class CNormalSerializer extends JsonSerializer<C> {
    @Override
    public void serialize(C value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException {
        gen.writeRawValue(new ObjectMapper().writeValueAsString(value));
    }
}

@JsonFilter(JsonFieldFilter.JSON_FILTER)
public class JsonFieldFilter {
    public static final String JSON_FILTER = "Json filter";
}

public class X {
    public static void main(String[] args) {
        ObjectMapper objectMapper = new ObjectMapper();
        // registered standard C serializer
        SimpleModule simpleModule = new SimpleModule();
        CNormalSerializer cSerializer = new CNormalSerializer ();
        simpleModule.addSerializer(C.class, cSerializer);
        objectMapper.registerModule(simpleModule);
        // added the 'a' filter
        objectMapper.addMixIn(Object.class, JsonFieldFilter.class);
        String[] ignorableFieldNames = {"a"};
        FilterProvider filters = new SimpleFilterProvider().addFilter(JsonFieldFilter.JSON_FILTER, SimpleBeanPropertyFilter.serializeAllExcept(ignorableFieldNames));
        ObjectWriter writer = objectMapper.writer(filters);

        writer.writeValueAsString(new A());
    }
}

Put @JsonIgnoreProperties(ignoreUnknown = true) annotation to your class where you need to skip that field. It will look like this:

@JsonIgnoreProperties(ignoreUnknown = true)
public class A {
    public B b;
    public C c;
    public D d;
    public E e;
}

public class B {
    public int a;
}

public class C {
    public int a;
    public D d;
}

public class D {
    public int a;
}

@JsonIgnoreProperties(ignoreUnknown = true)
public class E {
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM