Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to include only specific properties when serializing with Jackson

I am trying to implement a universal method which serializes the given object to JSON, but only those properties which are passed in a collection. If possible I want to get this functionality without specifying @JsonFilter on the class. For this I am trying to use FilterExceptFilter from Jackson 2.4.1. Dependencies:

  • jackson-core-2.4.1.jar
  • jackson-databind-2.4.1.jar
  • jackson-annotations-2.4.0.jar

Here is what I have at the moment:

public static String serializeOnlyGivenFields(Object o,
                    Collection<String> fields) throws JsonProcessingException {
    if ((fields == null) || fields.isEmpty()) return null;

    Set<String> properties = new HashSet<String>(fields);

    SimpleBeanPropertyFilter filter =
        new SimpleBeanPropertyFilter.FilterExceptFilter(properties);
    SimpleFilterProvider fProvider = new SimpleFilterProvider();
    fProvider.addFilter("fieldFilter", filter);
    fProvider.setDefaultFilter(filter);

    ObjectMapper mapper = new ObjectMapper();
    mapper.setFilters(fProvider);

    String json = mapper.writeValueAsString(o);
    return json;
}

However, the filter is never applied. It always serializes all properties.

Set<String> fields = new HashSet<String>(); fields.add("name");
String json = Serializer.serializeOnlyGivenFields(e, fields);
System.out.println(json);

{"name":"Test entity","description":"Test description"}

I have also tried to register the FilterProvider on the ObjectWriter, but same result:

String json = mapper.writer(fProvider).writeValueAsString(o);

What am I missing? Is there a nice way to achieve this with Jackson?

like image 896
Daniel Szalay Avatar asked Oct 22 '14 13:10

Daniel Szalay


People also ask

Can Jackson only serialize a field if it meet a criteria?

Overview This tutorial is going to illustrate how we can use Jackson to only serialize a field if it meets a specific, custom criteria. For example, say we only want to serialize an integer value if it's positive – and we want to skip it entirely if it's not.

Can I ignore certain fields when serializing an object to JSON?

1. Overview This tutorial will show how to ignore certain fields when serializing an object to JSON using Jackson 2.x. This is very useful when the Jackson defaults aren't enough and we need to control exactly what gets serialized to JSON — and there are several ways to ignore properties.

Can I serialize or deserialize Jackson objects in Spring Boot?

And when you're serializing or deserializing them with Jackson in your Spring Boot application, you just want to ignore them. For example, you might store the user's password.

Is there a more flexible alternative to JSON serialization?

A more flexible but also more complex alternative would be using a fully custom serializer to control the JSON output – so if this solution isn't flexible enough, it may be worth looking into that.


1 Answers

Based on http://www.cowtowncoder.com/blog/archives/2011/09/entry_461.html an alternate way to set up the filter is setting up a class that extends JacksonAnnotationIntrospector and overrides findFilterId. You can then specify to find your filter in the findFilterId. This could be made to be as robust if you want based on some other map or algorithm. Below is sample code. Not sure if the performance is better than the solution above but it seems to be simpler and probably more easily extensible. I was doing this for serializing CSV using Jackson. Any feedback is welcome!

public class JSON {

private static String FILTER_NAME = "fieldFilter";

public static String serializeOnlyGivenFields(Object o,
                                              Collection<String> fields) throws JsonProcessingException {
    if ((fields == null) || fields.isEmpty()) fields = new HashSet<String>();

    Set<String> properties = new HashSet<String>(fields);

    SimpleBeanPropertyFilter filter =
            new SimpleBeanPropertyFilter.FilterExceptFilter(properties);
    SimpleFilterProvider fProvider = new SimpleFilterProvider();
    fProvider.addFilter(FILTER_NAME, filter);

    ObjectMapper mapper = new ObjectMapper();
    mapper.setAnnotationIntrospector( new AnnotationIntrospector() );

    String json = mapper.writer(fProvider).writeValueAsString(o);
    return json;
}

private static class AnnotationIntrospector extends JacksonAnnotationIntrospector {
    @Override
    public Object findFilterId(Annotated a) {
        return FILTER_NAME;
    }
}

}
like image 162
Rob Baily Avatar answered Sep 21 '22 08:09

Rob Baily