How to Dynamically Ignore Fields in Jackson
Jackson is a popular Java library for JSON processing. Sometimes, we need to ignore fields dynamically at runtime instead of using static annotations like @JsonIgnore
. This article explores various approaches to dynamically ignoring fields in Jackson.
1. Default Behavior and Static Field Ignoring
Before handling dynamic field ignoring, let’s see Jackson’s default behaviour and how fields are statically ignored.
1.1 Default Behavior
By default, Jackson serializes all fields of a Java object unless explicitly ignored.
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 | public class Product { private String name; private double price; public String getName() { return name; } public void setName(String name) { this .name = name; } public double getPrice() { return price; } public void setPrice( double price) { this .price = price; } } |
01 02 03 04 05 06 07 08 09 10 11 12 | public class DefaultSerialization { public static void main(String[] args) throws Exception { ObjectMapper mapper = new ObjectMapper(); Product product = new Product(); product.setName( "Laptop" ); product.setPrice( 1200.50 ); String json = mapper.writeValueAsString(product); System.out.println(json); } } |
Output:
1 | { "name" : "Laptop" , "price" :1200.5} |
1.2 Using @JsonIgnore
to Statically Ignore Fields
If we want to always exclude a field, we can use @JsonIgnore
.
1 2 3 4 5 6 7 8 9 | import com.fasterxml.jackson.annotation.JsonIgnore; public class Product { private String name; @JsonIgnore private double price; } |
01 02 03 04 05 06 07 08 09 10 11 12 | public class StaticIgnore { public static void main(String[] args) throws Exception { ObjectMapper mapper = new ObjectMapper(); Product product = new Product(); product.setName( "Laptop" ); product.setPrice( 1200.50 ); String json = mapper.writeValueAsString(product); System.out.println(json); } } |
Output:
1 | { "name" : "Laptop" } |
The @JsonIgnore
annotation works well for static exclusions, but let’s explore dynamic approaches.
2. Dynamically Ignoring Fields in Jackson
2.1 Using SimpleBeanPropertyFilter
and @JsonFilter
We can dynamically exclude fields using Jackson’s SimpleBeanPropertyFilter
.
1 2 3 4 5 6 7 8 | import com.fasterxml.jackson.annotation.JsonFilter; @JsonFilter ( "dynamicFilter" ) public class Product { private String name; private double price; } |
The @JsonFilter("dynamicFilter")
annotation in the Product
class enables dynamic field filtering during JSON serialization using Jackson. Unlike static annotations like @JsonIgnore
, which permanently exclude fields, @JsonFilter
allows selective exclusion at runtime. The filter name "dynamicFilter"
serves as an identifier that can be referenced in a FilterProvider
configuration.
This setup allows the ObjectMapper
to apply different filtering rules dynamically, determining which fields to include or ignore based on specific conditions.
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 | import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter; import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; public class DynamicFilterExample { public static void main(String[] args) throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.setFilterProvider( new SimpleFilterProvider().addFilter( "dynamicFilter" , SimpleBeanPropertyFilter.serializeAllExcept( "price" ) )); Product product = new Product(); product.setName( "Laptop" ); product.setPrice( 1200.50 ); String json = mapper.writeValueAsString(product); System.out.println(json); } } |
The DynamicFilterExample
class above demonstrates how to use Jackson’s SimpleBeanPropertyFilter
to dynamically ignore a field during JSON serialization. The ObjectMapper
is configured with a SimpleFilterProvider
, which applies the filter named "dynamicFilter"
, ensuring that all fields except "price"
are serialized.
When a Product
object is created with a name
and price
, the ObjectMapper
processes it according to the filter, omitting the price
field from the output.
Output:
1 | { "name" : "Laptop" } |
3. Using Mixins for Dynamic Ignoring
Mixins let us override annotations at runtime without modifying the original class.
3.1 Define a mixin to ignore the price field
Mixins in Jackson provide a way to modify the serialization and deserialization behaviour of a class without altering its source code. By defining a separate interface and applying it at runtime, we can dynamically ignore specific fields.
1 2 3 4 5 6 7 | import com.fasterxml.jackson.annotation.JsonIgnore; public interface ProductMixin { @JsonIgnore double getPrice(); } |
In this code, ProductMixin
is an interface that applies the @JsonIgnore
annotation to the getPrice()
method instead of directly on the field. Since Jackson uses getters for serialization, this ensures that the price
field is ignored in the JSON output while keeping the Product
class unchanged.
By registering this mixin with an ObjectMapper
, we can dynamically exclude the price
field during serialization without modifying the original class, making this approach flexible and reusable for different contexts.
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 | import com.fasterxml.jackson.databind.ObjectMapper; public class MixinExample { public static void main(String[] args) throws Exception { ObjectMapper mapper = new ObjectMapper(); mapper.addMixIn(Product. class , ProductMixin. class ); Product product = new Product(); product.setName( "Laptop" ); product.setPrice( 1200.50 ); String json = mapper.writeValueAsString(product); System.out.println(json); } } |
In the MixinExample
class, Jackson’s addMixIn
method is used to dynamically modify the serialization behaviour of the Product
class without changing its source code. The line mapper.addMixIn(Product.class, ProductMixin.class);
associates the ProductMixin
interface with the Product
class, applying the annotations from the mixin to the target class.
Since ProductMixin
marks the getPrice()
method with @JsonIgnore
, Jackson will exclude the price
field from the JSON output when serializing a Product
object.
Output:
1 | { "name" : "Laptop" } |
4. Using @JsonView
for Conditional Serialization
Jackson’s @JsonView
allows controlling which fields are included in the serialized JSON output based on different visibility levels.
1 2 3 4 5 6 7 8 | public class Views { static class Public { } static class Admin extends Public { } } |
The Views
class defines two nested static classes, Public
and Admin
, which are used as Jackson JSON Views to control field visibility during serialization. The Admin
class extends Public
, meaning it inherits all the fields associated with the Public
view while also allowing additional fields to be included specifically for the Admin
view. When @JsonView(Views.Public.class)
is applied to a field, it will be visible in both Public
and Admin
views, while fields annotated with @JsonView(Views.Admin.class)
will only be serialized when the Admin
view is explicitly used.
01 02 03 04 05 06 07 08 09 10 11 | import com.fasterxml.jackson.annotation.JsonView; public class Product { @JsonView (Views.Public. class ) private String name; @JsonView (Views.Admin. class ) private double price; } |
In the following example, we define a Product
object and serialize it using both the Public
and Admin
views to demonstrate how Jackson filters fields dynamically.
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 | import com.fasterxml.jackson.databind.ObjectMapper; public class JacksonViewsExample { public static void main(String[] args) throws Exception { ObjectMapper mapper = new ObjectMapper(); Product product = new Product(); product.setName( "Laptop" ); product.setPrice( 1200.50 ); // Serialize with public view String publicJson = mapper.writerWithView(Views.Public. class ).writeValueAsString(product); System.out.println( "Public View: " + publicJson); // Serialize with admin view String adminJson = mapper.writerWithView(Views.Admin. class ).writeValueAsString(product); System.out.println( "Admin View: " + adminJson); } } |
In this code, an ObjectMapper
is used to serialize a Product
object using two different views. The writerWithView(Views.Public.class)
ensures that only fields marked with @JsonView(Views.Public.class)
are included in the output, while writerWithView(Views.Admin.class)
includes fields for both Public
and Admin
views.
Output:
5. Conclusion
In this article, we explored various approaches to dynamically ignoring fields in Jackson. We covered using @JsonFilter
for runtime filtering, mixins for modifying serialization behaviour without altering the original class, and @JsonView
to control field visibility. Each method provides flexibility in managing JSON output, making it easier to handle different serialization requirements in Java applications.
6. Download the Source Code
This article covered how to use Jackson in Java to dynamic ignore fields during JSON processing.
You can download the full source code of this example here: java jackson fields dynamic ignore