1

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.

Michał Ziober
  • 37,175
  • 18
  • 99
  • 146
suat
  • 4,239
  • 3
  • 28
  • 51

3 Answers3

2

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:

Michał Ziober
  • 37,175
  • 18
  • 99
  • 146
  • Thanks for your help. Actually the model is quite complicated preventing me from creating a corresponding MixIn class. I was able to solve the problem as in my answer. Thanks again! – suat Oct 16 '19 at 07:13
1

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());
    }
}
suat
  • 4,239
  • 3
  • 28
  • 51
0

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 {
}
Vault23
  • 743
  • 1
  • 5
  • 19