How do I exclude fields with Jackson not using annotations?
I need to exclude some fields by names before rendering. The list of fields is dynamic, so I can't use annotations.
I've tried to create custom serializer but I can't get field name there.
In GSON I've used ExclusionStrategy
, but Jackson has no such functionality. Is there an equivalent?
The below example of excluding fields by name is from my blog post, Gson v Jackson - Part 4. (Search for the PropertyFilterMixIn
.) This example demonstrates using a FilterProvider
with a SimpleBeanPropertyFilter
to serializeAllExcept
a user-specified list of field names.
@JsonFilter("filter properties by name")
class PropertyFilterMixIn {}
class Bar
{
public String id = "42";
public String name = "Fred";
public String color = "blue";
public Foo foo = new Foo();
}
class Foo
{
public String id = "99";
public String size = "big";
public String height = "tall";
}
public class JacksonFoo
{
public static void main(String[] args) throws Exception
{
ObjectMapper mapper = new ObjectMapper();
mapper.getSerializationConfig().addMixInAnnotations(
Object.class, PropertyFilterMixIn.class);
String[] ignorableFieldNames = { "id", "color" };
FilterProvider filters = new SimpleFilterProvider()
.addFilter("filter properties by name",
SimpleBeanPropertyFilter.serializeAllExcept(
ignorableFieldNames));
ObjectWriter writer = mapper.writer(filters);
System.out.println(writer.writeValueAsString(new Bar()));
// output:
// {"name":"James","foo":{"size":"big","height":"tall"}}
}
}
(Note: The relevant API may have changed slightly with a recent Jackson release.)
While the example does use a seemingly unnecessary annotation, the annotation is not applied to the fields to be excluded. (To help get the API changed to simplify the necessary configuration a bit, please don't hesitate to vote for implementation of issue JACKSON-274.
I wrote a library to deal with a similar use case. I needed to programmatically ignore fields based on the user requesting data. The normal Jackson options were just too heavy-handed, and I hated the way it made my code look.
The library makes this a whole lot easier to understand. It allows you to simply do this:
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.monitorjbl.json.JsonView;
import com.monitorjbl.json.JsonViewSerializer;
import static com.monitorjbl.json.Match.match;
//initialize jackson
ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addSerializer(JsonView.class, new JsonViewSerializer());
mapper.registerModule(module);
//get a list of the objects
List<MyObject> list = myObjectService.list();
String json;
if(user.getRole().equals('ADMIN')){
json = mapper.writeValueAsString(list);
} else {
json = mapper.writeValueAsString(JsonView.with(list)
.onClass(MyObject.class, match()
.exclude("*")
.include("name")));
}
System.out.println(json);
The code is available on GitHub, hope it helps!