Jackson Top

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

>> CHECK OUT THE COURSE

If you have a few years of experience in the Java ecosystem, and you're interested in sharing that experience with the community (and getting paid for your work of course), have a look at the "Write for Us" page. Cheers. Eugen

1. Overview

In this tutorial, we’ll see how to use both Jackson and Gson to map different JSON fields onto a single Java field.

2. Maven Dependencies

In order to use the Jackson and Gson libraries we need to add the following dependencies to our POM:

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.5</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.9.8</version>
    <scope>test</scope>
</dependency>

3. Sample JSON

Let’s imagine that we want to get the details of the weather for different locations into our Java application. We’ve found a couple of web sites that publish weather data as JSON documents. However, they use slightly different formats:

{
    "location": "London",
    "temp": 15,
    "weather": "Cloudy"
}

And:

{
    "place": "Lisbon",
    "temperature": 35,
    "outlook": "Sunny"
}

We want to deserialize both of these formats into the same Java class, named Weather:

public class Weather {
    private String location;
    private int temp;
    private String outlook;
}

So let’s take a look at how we can achieve this using both Jackson and Gson libraries.

4. Using Jackson

To achieve this, we’ll make use of Jackson’s @JsonProperty and @JsonAlias annotations. These will allow us to map more than one JSON property onto the same Java field.

First, we’re going to use the @JsonProperty annotation, so that Jackson knows the name of the JSON field to map. The value in the @JsonProperty annotation is used for both deserializing and serializing.

Then we can use the @JsonAlias annotation. As a result, Jackson will know the names of other fields in the JSON document that are mapped to the Java field. The value in the @JsonAlias annotation is only used for deserializing:

@JsonProperty("location")
@JsonAlias("place")
private String location;
@JsonProperty("temp")
@JsonAlias("temperature")
private int temp;

@JsonProperty("outlook")
@JsonAlias("weather")
private String outlook;

Now that we’ve added the annotations, let’s use Jackson’s ObjectMapper to create Java objects using the Weather class:

@Test
public void givenTwoJsonFormats_whenDeserialized_thenWeatherObjectsCreated() throws Exception {

    ObjectMapper mapper = new ObjectMapper();

    Weather weather = mapper.readValue("{\n"  
      + "  \"location\": \"London\",\n" 
      + "  \"temp\": 15,\n" 
      + "  \"weather\": \"Cloudy\"\n" 
      + "}", Weather.class);

    assertEquals("London", weather.getLocation());
    assertEquals("Cloudy", weather.getOutlook());
    assertEquals(15, weather.getTemp());

    weather = mapper.readValue("{\n" 
      + "  \"place\": \"Lisbon\",\n" 
      + "  \"temperature\": 35,\n"
      + "  \"outlook\": \"Sunny\"\n"
      + "}", Weather.class);

    assertEquals("Lisbon", weather.getLocation());
    assertEquals("Sunny", weather.getOutlook());
    assertEquals(35, weather.getTemp());
}

5. Using Gson

Now, let’s try the same with Gson. We’ll need to use the value and the alternate parameters in the @SerializedName annotation.

The first one will be used as a default, while the second will be used to indicate an alternate name of the JSON field that we want to map:

@SerializedName(value="location", alternate="place")
private String location;
@SerializedName(value="temp", alternate="temperature")
private int temp;

@SerializedName(value="outlook", alternate="weather")
private String outlook;

Now that we’ve added the annotations, let’s test our example:

@Test
public void givenTwoJsonFormats_whenDeserialized_thenWeatherObjectsCreated() throws Exception {
        
    Gson gson = new GsonBuilder().create();
    Weather weather = gson.fromJson("{\n" 
      + "  \"location\": \"London\",\n" 
      + "  \"temp\": 15,\n" 
      + "  \"weather\": \"Cloudy\"\n" 
      + "}", Weather.class);
        
    assertEquals("London", weather.getLocation());
    assertEquals("Cloudy", weather.getOutlook());
    assertEquals(15, weather.getTemp());
        
    weather = gson.fromJson("{\n"
      + "  \"place\": \"Lisbon\",\n"
      + "  \"temperature\": 35,\n"
      + "  \"outlook\": \"Sunny\"\n"
      + "}", Weather.class);
       
    assertEquals("Lisbon", weather.getLocation());
    assertEquals("Sunny", weather.getOutlook());
    assertEquals(35, weather.getTemp());
        
}

6. Conclusion

We saw that by using either Jackson’s @JsonAlias or Gson’s alternate parameter, we can easily convert different JSON formats into the same Java object.

You’ll find the examples in the Jackson and the Gson projects on GitHub.

Jackson bottom

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

>> CHECK OUT THE COURSE