---
title: Polymorphism and Inheritance with Jackson
url: https://blog.octoperf.com/polymorphism-and-inheritance-with-jackson/
date: '2018-02-01'
authors:
- jloisel
categories:
- Development
tags:
- Java
description: Learn how to serialize and deserialize polymorphic object trees with Jackson Json Databind. Using practical code examples to make it easy to understand.
---

# Polymorphism and Inheritance with Jackson

[Jackson Json](https://github.com/FasterXML/jackson) is a powerful Java library to serialize and deserialize objects to/from [Json](https://www.json.org/).

You may ask yourself: 

- **How can I serialize and deserialize polymorphic class instances?**
- **How to configure Jackson to serialize objects being represented by their interface?**

Good news! The answer is just below.


It's somehow difficult to find real examples showing how to do this. That's why I've decided to make this little tutorial to help you get the idea quickly with practical code examples.

## Polymorphism

Polymorphism is the ability to have different implementations represented by a single interface or abstract class. This article describes how to serialize and deserialize objects by their interface, as well as **Polymorphic Tree Structured** object instances.

Please note this example is written in *Java 8* and uses [Lombok](https://projectlombok.org/). Lombok has numerous benefits like generating getters, toString, equals and hashcode methods.

## Dependencies

First, let's add the Maven dependencies to our `pom.xml`:

```xml

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

```

It's recommended to always use the latest version. Check [Jackson Databind](https://search.maven.org/#search%7Cga%7C1%7Ca%3A%22jackson-databind%22) on Maven Central.

## Example

Let's take the following example:

```java

public interface Vehicle {

  String getName();
}
```

It has a `Car` implementation:

```java
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Value;

import static java.util.Objects.requireNonNull;

@Value
public class Car implements Vehicle {
  String name;

  @JsonCreator
  public Car(@JsonProperty("name") final String name) {
    this.name = requireNonNull(name);
  }
}
```

And a `Truck` implementation:


```java

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Value;

import static java.util.Objects.requireNonNull;

@Value
public class Truck implements Vehicle {
  String name;

  @JsonCreator
  public Truck(@JsonProperty("name") final String name) {
    this.name = requireNonNull(name);
  }
}

```

## Implementations

The `Vehicle` interface has two implementations: `Car` and `Truck`. Now let's suppose we want to serialize the following object:

```java

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Value;

import java.util.List;

import static java.util.Objects.requireNonNull;

@Value
public class Vehicles {
  List<Vehicle> vehicles;

  @JsonCreator
  public Vehicles(@JsonProperty("vehicles") final List<Vehicle> vehicles) {
    super();
    this.vehicles = requireNonNull(vehicles);
  }
}

```

## Configure Jackson Json

In order to be able to serialize / deserialize the `Vehicles` instance, Jackson Json needs to know how to instantiate a `Vehicle` instance. It needs to know whenever it's a `Truck` or a `Car` instance. In order to do this, **Jackson Json** must be configured. There are **several ways** to do so.

### Direct mapping

In the following example, the mapping is directly configured on the `Vehicle` interface:

```java

import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;

import static com.fasterxml.jackson.annotation.JsonTypeInfo.As.PROPERTY;
import static com.fasterxml.jackson.annotation.JsonTypeInfo.Id.NAME;

@JsonTypeInfo(use = NAME, include = PROPERTY)
@JsonSubTypes({
  @JsonSubTypes.Type(value=Truck.class, name = "Truck"),
  @JsonSubTypes.Type(value=Car.class, name = "Car")
})
public interface Vehicle {

  String getName();
}

```

This solution works well when the interface and the implementation are placed within the same package. However, it introduces a **cyclic dependency** between the `Vehicle` interface and its implementations.

### Type mapping

The other solution is the configure the **type mapping** separately on the `ObjectMapper`. Let's see how in this [JUnit](https://junit.org/) test:


```java

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.NamedType;
import com.google.common.collect.ImmutableList;
import org.junit.Test;

import java.io.IOException;

import static org.junit.Assert.assertEquals;

public class VehicleTest {

  private static final ObjectMapper MAPPER = new ObjectMapper();

  static {
    MAPPER.registerSubtypes(new NamedType(Truck.class, "Truck"));
    MAPPER.registerSubtypes(new NamedType(Car.class, "Car"));
  }

  @Test
  public void shouldSerializeVehicles() throws IOException {
    final Vehicles vehicles = new Vehicles(ImmutableList.of(new Car("Dodge"), new Truck("Scania")));
    final String json = MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(vehicles);
    final Vehicles read = MAPPER.readValue(json, Vehicles.class);
    assertEquals(vehicles, read);
  }
}

```

This JUnit does the following:

- It configures the **type mapping** in a `static` block. A `Truck` instance is mapped to the named type *Truck* for example,
- And It runs a JUnit which checks the serialization / deserialization produces exactly the same object.

If we take a look at the produced Json, it looks like the following:

```json

{
  "vehicles" : [ {
    "@type" : "Car",
    "name" : "Dodge"
  }, {
    "@type" : "Truck",
    "name" : "Scania"
  } ]
}

```

Jackson has added a `@type` attribute to each vehicle json. This **special attribute** is used to identify the type of vehicle being serialized. Jackson then uses this information during deserialization to create the right class instance.

## Polymorphic tree structure

### Serialization

Great! Now that we've covered a basic example, let's see how to serialize a **polymorphic tree structure**. Here is an example:

```java

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Value;

import java.util.List;

@Value
public class CarTransporter implements Vehicle {
  String name;
  List<Vehicle> vehicles;

  @JsonCreator
  public CarTransporter(
    @JsonProperty("name") final String name,
    @JsonProperty("vehicles") final List<Vehicle> vehicles) {
    super();
    this.name = requireNonNull(name);
    this.vehicles = requireNonNull(vehicles);
  }
}

```

A `CarTransporter` is a `Vehicle` itself! But, it's also able to carry `Vehicle` instances. In fact, it could technically carry another `CarTransporter` although a real one wouldn't be able too... It's not the point here.

### Unit test

Now let's include another **unit-test** to try this out:

```java

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.NamedType;
import com.google.common.collect.ImmutableList;
import org.junit.Test;

import java.io.IOException;

import static org.junit.Assert.assertEquals;

public class VehicleTest {

  private static final ObjectMapper MAPPER = new ObjectMapper();

  static {
    MAPPER.registerSubtypes(new NamedType(Truck.class, "Truck"));
    MAPPER.registerSubtypes(new NamedType(Car.class, "Car"));
    MAPPER.registerSubtypes(new NamedType(CarTransporter.class, "CarTransporter"));
  }

  @Test
  public void shouldSerializeCarTransporter() throws IOException {
    final Vehicle transporter = new CarTransporter("Transporter", ImmutableList.of(new Car("Dodge"), new Truck("Scania")));
    final String json = MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(transporter);
    final Vehicle read = MAPPER.readValue(json, Vehicle.class);
    assertEquals(transporter, read);
  }

}

```

### Json

As you can see, I've added the `CarTransporter` type mapping. The unit-test above serializes and deserializes a `CarTransporter` instance. The produced json looks like the following:

```json

{
  "@type" : "CarTransporter",
  "name" : "Transporter",
  "vehicles" : [ {
    "@type" : "Car",
    "name" : "Dodge"
  }, {
    "@type" : "Truck",
    "name" : "Scania"
  } ]
}

```

I hope you see now that there is nothing difficult here! **Jackson can serialize and deserialize polymorphic data structures** very easily. The `CarTransporter` can itself carry another `CarTransporter` as a vehicle: that's where the **tree structure** is!

Now, you know how to configure Jackson to serialize and deserialize objects being represented by their interface.
