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

Simple Inheritance with Jackson

$
0
0

1. Overview

In this tutorial, we’re going to take a look at inheritance and in particular how to handle JSON serialization and deserialization of Java classes that extend a superclass.

In order to get started with Jackson, you can have a look at this article here.

2. JSON Inheritance – Real World Scenario

Let’s say that we have an abstract Event class which is used for some sort of event processing:

abstract public class Event {
    private String id;
    private Long timestamp;

    // standard constructors, getters/setters
}

There are two subclasses that extend the Event class, the first is ItemIdAddedToUser, and the second is ItemIdRemovedFromUser.

The problem is that if we want to represent these classes as JSON, we would need to serialize their type information in addition to their ordinary fields. Otherwise, when deserializing into an Event there would be no way of knowing what subclass the JSON represents. Fortunately, there is a mechanism to achieve this in the Jackson library.

3. Implementing Inheritance Using Jackson

There is a @JsonTypeInfo annotation that allows us to store an object’s type information as a JSON field.

Let’s enrich the Event class with the annotation:

@JsonTypeInfo(
  use = JsonTypeInfo.Id.MINIMAL_CLASS,
  include = JsonTypeInfo.As.PROPERTY,
  property = "eventType")
abstract public class Event {
    private String id;
    private Long timestamp;

    @JsonCreator
    public Event(
      @JsonProperty("id") String id,
      @JsonProperty("timestamp") Long timestamp) {
 
        this.id = id;
        this.timestamp = timestamp;
    }
    
    // standard getters
}

In this case, using the annotation will cause the ObjectMapper to add an additional field called eventType to the resulting JSON, with a value equal to the object’s type. By using JsonTypeInfo.Id. MINIMAL_CLASS, it means that the value of the eventType property will be equal to the name of the class. Let’s serialize an instance of an ItemIdRemovedFromUserEvent:

Event event = new ItemIdRemovedFromUser("1", 12345567L, "item_1", 2L);
ObjectMapper objectMapper = new ObjectMapper();
String eventJson = objectMapper.writeValueAsString(event);

When we print the JSON we will now see that the additional type information is stored:

{  
    "eventType":".ItemIdRemovedFromUser",
    "id":"1",
    "timestamp":12345567,
    "itemId":"item_1",
    "quantity":2
}

Let’s validate that the deserialization works by asserting that the ObjectMapper creates an instance of an ItemIdRemovedFromUser class:

@Test
public void givenRemoveItemJson_whenDeserialize_shouldHaveProperClassType()
  throws IOException {
 
    //given
    Event event = new ItemIdRemovedFromUser("1", 12345567L, "item_1", 2L);
    ObjectMapper objectMapper = new ObjectMapper();
    String eventJson = objectMapper.writeValueAsString(event);

    //when
    Event result = new ObjectMapper().readValue(eventJson, Event.class);

    //then
    assertTrue(result instanceof ItemIdRemovedFromUser);
    assertEquals("item_1", ((ItemIdRemovedFromUser) result).getItemId());
}

6. Ignoring Fields From a Super-Class

Let’s say that we want to extend an Event class, but we want our ObjectMapper to ignore it’s id field so it is not present in the resulting JSON.

It’s quite easily achieve this by using the @JsonIgnoreProperties annotation:

@JsonIgnoreProperties("id")
public class ItemIdAddedToUser extends Event {
    private String itemId;
    private Long quantity;

    @JsonCreator
    public ItemIdAddedToUser(
      @JsonProperty("id") String id,
      @JsonProperty("timestamp") Long timestamp,
      @JsonProperty("itemId") String itemId,
      @JsonProperty("quantity") Long quantity) {
 
        super(id, timestamp);
        this.itemId = itemId;
        this.quantity = quantity;
    }

    // standard getters
}

Let’s serialize an ItemAddedToUserEvent, and see which fields are ignored by the ObjectMapper:

Event event = new ItemIdAddedToUser("1", 12345567L, "item_1", 2L);
ObjectMapper objectMapper = new ObjectMapper();
String eventJson = objectMapper.writeValueAsString(event);

The resulting JSON will look like this (note that there is no id field from Event super-class):

{  
    "eventType":".ItemIdAddedToUser",
    "timestamp":12345567,
    "itemId":"item_1",
    "quantity":2
}

Let’s assert that the id field is missing with a test case:

@Test
public void givenAdddItemJson_whenSerialize_shouldIgnoreIdPropertyFromSuperclass()
  throws IOException {
 
    // given
    Event event = new ItemIdAddedToUser("1", 12345567L, "item_1", 2L);
    ObjectMapper objectMapper = new ObjectMapper();
        
    // when
    String eventJson = objectMapper.writeValueAsString(event);

    // then
    assertFalse(eventJson.contains("id"));
}

7. Conclusion

This article demonstrates how to use inheritance with Jackson library.

The implementation of all these examples and code snippets can be found in the GitHub project – this is a Maven project, so it should be easy to import and run as it is.


Viewing all articles
Browse latest Browse all 4536

Trending Articles



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