Quantcast
Channel: Baeldung
Viewing all articles
Browse latest Browse all 3670

Dynamically Ignoring Fields in Jackson

$
0
0

1. Introduction

In this tutorial, we’ll learn how to ignore fields dynamically in Jackson.

This is useful when we want to serialize and deserialize the same object differently, based on particular conditions.

We’ll explore three approaches for achieving this: @JsonFilter, @JsonView, and Jackson Mixins.

2. Project Setup

Let’s start our tutorial by adding the required Jackson library:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.17.2</version>
</dependency>

The last version can be found here.

3. Dynamic Ignore Using @JsonFilter

The first approach we’ll examine is through an annotation that specifies a filter to use during serialization.

By annotating a class with @JsonFilter:

@JsonFilter("publicFilter")
public class UserWithFilter {
    private Long id;
    private String name;
    // getters and setters
}

We can dynamically configure the ObjectMapper and register a PropertyFilter to serialize all the fields except the id:

SimpleFilterProvider filterProvider = new SimpleFilterProvider();
filterProvider.addFilter("publicFilter", SimpleBeanPropertyFilter.serializeAllExcept("id"));
ObjectMapper objectMapper = new ObjectMapper().setFilterProvider(filterProvider);

Then we can serialize the UserWithFilter object:

UserWithFilter user = new UserWithFilter(1000L, "John");
String result = objectMapper.writeValueAsString(user);
assertThat(result).contains("John");
assertThat(result).doesNotContain("1000")

This method provides huge flexibility since we can choose which fields to serialize at runtime.

Unfortunately, this method does not work for dynamically deserializing objects: even if we customize the ObjectMapper with the same filter provider, the id field will be unmarshalled in the object:

String json = "{\"id\":1000,\"name\":\"John\"}";
UserWithFilter result = objectMapper.readValue(json, UserWithFilter.class);
assertEquals(1000L, result.getId());
assertEquals("John", result.getName());

In the next section, we’ll see another approach that works also when deserializing objects.

4. Conditional Ignore Using @JsonView

@JsonView is a way to control field visibility by defining different views. Unlike the previous approach, we need to define serialization options at compile time:

public class UserWithView {
    @JsonView(InternalView.class)
    private Long id;
    @JsonView(PublicView.class)
    private String name;
    // getters and setters
    public interface PublicView {}
    public interface InternalView extends PublicView {}
}

At runtime, we can instead select the right JsonView to use when serializing objects by configuring the ObjectMapper:

ObjectWriter objectWriter = new ObjectMapper().writerWithView(UserWithView.PublicView.class);

In this case, the result will not contain the ID field, which is included in the InternalView only:

String result = objectWriter.writeValueAsString(user);
assertThat(result).contains("John");
assertThat(result).doesNotContain("1000")

The @JsonView dynamic approach works also when unmarshalling Json into Objects:

String json = "{\"id\":1000,\"name\":\"John\"}";
ObjectReader objectReader = new ObjectMapper().readerWithView(UserWithView.PublicView.class)
  .forType(UserWithView.class);
UserWithView user = objectReader.readValue(json);
assertEquals("John", user.getName());
assertNull(user.getId());

When deserializing we need to use the readerWithView() rather than the writerWithView() method to customize the ObjectMapper.

5. Use Mixins to apply @JsonIgnore Dynamically

Jackson Mixins provide a way to apply @JsonIgnore annotations without modifying the original class. We need to define an interface with a getter method on the property we want to ignore:

public interface PublicMixin {
    @JsonIgnore
    Long getId();
}

Then we can register the interface as a Mixin in the ObjectMapper and achieve the desired behavior:

ObjectMapper objectMapper = new ObjectMapper().addMixIn(UserWithMixin.class, PublicMixin.class);
String result = objectMapper.writeValueAsString(user);
assertThat(result).contains("John");
assertThat(result).doesNotContain("1000");

The @JsonIgnore annotation which is dynamically injected with the mixin configuration, makes Jackson ignore fields also when deserializing objects:

String json = "{\"id\":1000,\"name\":\"John\"}";
ObjectMapper objectMapper = new ObjectMapper().addMixIn(UserWithMixin.class, UserWithMixin.PublicMixin.class);
UserWithMixin user = objectMapper.readValue(json, UserWithMixin.class);
assertNull(user.getId());
assertEquals("John", user.getName());

In this case, serialization and deserialization don’t need a specific customization. It’s enough to set the right Mixin class.

In the next section, we’ll summarize all three approaches we have evaluated.

6. Comparing the Approaches

Let’s compare the approaches in terms of flexibility, serialization/deserialization, and best use cases:

Approach Runtime Flexibility Use Case Serialization / Deserialization
@JsonFilter High Exclude fields dynamically at runtime No
@JsonView Medium Define at compile time multiple serialization views to switch dynamically at runtime Yes
Mixins Medium Apply @JsonIgnore without modifying the original class Yes

This table summarizes the strengths and trade-offs of each approach. Mostly the decision of which one to pick will vary if we need deserialization to work as well as serialization, if we have high runtime flexibility needs, or if we won’t edit the existing source code.

7. Conclusion

In this article, we have seen some approaches to achieve dynamicity when serializing and deserializing objects with Jackson. Full runtime dynamicity is difficult to achieve with compiled languages such as Java. Jackson, however, provides several mechanisms to customize serialization behavior and adapt outputs based on different runtime needs.

The code belonging to the above examples is available over on GitHub.

The post Dynamically Ignoring Fields in Jackson first appeared on Baeldung.
       

Viewing all articles
Browse latest Browse all 3670

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>