user1596371
user1596371

Reputation:

Jackson serialize a subset of a map

I have a map which I want to serialize using Jackson but only want to serialize a subset of it. Say I have a simple map as follows:

final Map<String, String> map = new HashMap<>();
map.put("key 1", "value 1");
map.put("key 2", "value 2");
map.put("_internal key 1", "value 3");
map.put("_internal key 2", "value 4");

Then when serializing this I want to filter out any item whose key starts with _, so that the serialized representation would be {'key 1': 'value 1','key 2': 'value 2'}.

I started looking at @JsonFilter but can't find any examples beyond very simplistic ones against basic types and nothing which appears to help with this more advanced type of filtering.

What's the best way to provide this custom serialization?

This is using Jackson 2.4, in case it matters.

Upvotes: 3

Views: 2311

Answers (1)

Alexey Gavrilov
Alexey Gavrilov

Reputation: 10853

You can achieve this by defining a Jackson filter which outputs the keys that don't start with an underscore, and enable this filter for all the Map classes via the annotation introspector. Here is an example:

public class JacksonMapSubset {

    public static void main(String[] args) throws JsonProcessingException {
        final Map<String, String> map = new HashMap<>();
        map.put("key 1", "value 1");
        map.put("key 2", "value 2");
        map.put("_internal key 1", "value 3");
        map.put("_internal key 2", "value 4");

        ObjectMapper mapper = new ObjectMapper();

        SimpleFilterProvider filters = new SimpleFilterProvider();
        final String filterName = "exclude-starting-with-underscore";
        mapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector() {
            @Override
            public Object findFilterId(Annotated a) {
                if (Map.class.isAssignableFrom(a.getRawType())) {
                    return filterName;
                }
                return super.findFilterId(a);
            }
        });
        filters.addFilter(filterName, new SimpleBeanPropertyFilter() {
            @Override
            protected boolean include(BeanPropertyWriter writer) {
                return true;
            }

            @Override
            protected boolean include(PropertyWriter writer) {
                return !writer.getName().startsWith("_");
            }
        });

        mapper.setFilters(filters);
        System.out.println(mapper.writeValueAsString(map));
    }
}

Output:

{"key 1":"value 1","key 2":"value 2"}

Upvotes: 4

Related Questions