4

I have a class like

interface IHideable {
   boolean isHidden();
}

class Address implements IHideable {
    private String city;
    private String street;
    private boolean hidden;
}

class PersonalInfo implements IHideable {
    private String name;
    private int age;
    private boolean hidden;
}

I want to serialize a List of IHideable in my web service; but filter out any object which has the hidden field set to true.

Basically given with a list of objects like

[
{'city 1','street 1',false},
{'city 2','street 2',true},
{'city 3','street 3',false}
]

I want the output as

[
  {
    city:'city 1',
    street:'street 1'
  },
  {
    city:'city 3',
    street:'street 3'
  }
]

I tried the following implementation

class ItemSerializer extends JsonSerializer<IHideable> {  
    @Override
    public void serialize(IHideable value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {

        if (!value.isHidden()) {
            jgen.writeStartObject();
            jgen.writeString("city", value.city);
            jgen.writeString("street", value.street);
            jgen.writeEndObject();
        }
    }
}

But the writeString methods written are specific for Address class. When i use writeObject there it throws stackoverflow exception. Can I use some generic writeObject method which Can write any object which implements IHideable()? Is this possible with jackson default/custom serialization?

Michał Ziober
  • 37,175
  • 18
  • 99
  • 146
falcon
  • 1,332
  • 20
  • 39

1 Answers1

5

You can use BeanSerializerModifier to register a serializer for IHideable types and get the reference to the default bean serializer as it was discussed in this question.

In your serializer you check the isHidden flag and if it is not set serialize the instance using the default serializer. That trick should work for any types that implements your IHideable interface. Here is an example:

public class JacksonHide {
    @JsonIgnoreProperties("hidden")
    public static interface IHideable {
        boolean isHidden();
    }

    public static class Address implements IHideable {
        public final String city;
        public final String street;
        public final boolean hidden;

        public Address(String city, String street, boolean hidden) {
            this.city = city;
            this.street = street;
            this.hidden = hidden;
        }

        @Override
        public boolean isHidden() {
            return hidden;
        }
    }

    public static class PersonalInfo implements IHideable {
        public final String name;
        public final int age;
        public final boolean hidden;

        public PersonalInfo(String name, int age, boolean hidden) {
            this.name = name;
            this.age = age;
            this.hidden = hidden;
        }

        @Override
        public boolean isHidden() {
            return hidden;
        }
    }

    private static class MyBeanSerializerModifier extends BeanSerializerModifier {
        @Override
        public JsonSerializer<?> modifySerializer(SerializationConfig config,
                                                  BeanDescription beanDesc,
                                                  JsonSerializer<?> serializer) {
            if (IHideable.class.isAssignableFrom(beanDesc.getBeanClass())) {
                return new MyIHideableJsonSerializer((JsonSerializer<IHideable>) serializer);
            }
            return super.modifySerializer(config, beanDesc, serializer);
        }

        private static class MyIHideableJsonSerializer extends JsonSerializer<IHideable> {
            private final JsonSerializer<IHideable> serializer;

            public MyIHideableJsonSerializer(JsonSerializer<IHideable> serializer) {
                this.serializer = serializer;
            }

            @Override
            public void serialize(IHideable value,
                                  JsonGenerator jgen,
                                  SerializerProvider provider) throws IOException {
                if (!value.isHidden()) {
                     serializer.serialize(value, jgen, provider);
                }

            }
        }
    }

    public static void main(String[] args) throws JsonProcessingException {
        ObjectMapper mapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.setSerializerModifier(new MyBeanSerializerModifier());
        mapper.registerModule(module);

        PersonalInfo p1 = new PersonalInfo("John", 30, false);
        PersonalInfo p2 = new PersonalInfo("Ivan", 20, true);
        Address a1 = new Address("A", "B", false);
        Address a2 = new Address("C", "D", true);

        System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString
                (Arrays.asList(p1, p2, a1, a2)));
    }

}

Output:

[ {
  "name" : "John",
  "age" : 30
}, {
  "city" : "A",
  "street" : "B"
} ]
Community
  • 1
  • 1
Alexey Gavrilov
  • 10,593
  • 2
  • 38
  • 48
  • I had to use `SimpleModule module = new SimpleModule("dummy", new Version(1, 0, 0, null)) { public void setupModule(SetupContext context) { super.setupModule(context); context.addBeanSerializerModifier(new MySerializerModifier());}};` But otherwise it worked perfectly. Thank you! – falcon Aug 07 '14 at 09:21
  • I believe this is cyclic inheritance and should be outside , https://stackoverflow.com/questions/23811904/cyclic-inheritance-when-implementing-inner-interface-in-enum – shareef Jun 10 '18 at 22:58