Mapping Multiple JSON Fields to a Single Java Field – 将多个JSON字段映射到单个Java字段上

最后修改: 2019年 3月 14日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

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

在本教程中,我们将看到如何使用Jackson和Gson将不同的JSON字段映射到单一的Java字段。

2. Maven Dependencies

2.Maven的依赖性

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

为了使用JacksonGson库,我们需要在我们的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.13.0</version>
    <scope>test</scope>
</dependency>

3. Sample JSON

3.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:

让我们想象一下,我们想在我们的Java应用程序中获取不同地点的天气细节。我们发现有几个网站将天气数据作为JSON文档发布。然而,它们使用的格式略有不同。

{
    "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:

我们想把这两种格式反序列化为同一个Java类,命名为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.

因此,让我们来看看我们如何使用Jackson和Gson库来实现这一目标。

4. Using Jackson

4.使用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.

为了实现这一目标,我们将利用Jackson的@JsonProperty@JsonAlias注释。这些将允许我们将多个JSON属性映射到同一个Java字段上

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.

首先,我们要使用@JsonProperty注解,这样Jackson就知道要映射的JSON字段的名称。@JsonProperty注解中的值被用于反序列化和序列化。

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:

然后我们可以使用@JsonAlias注解。因此,Jackson将知道JSON文档中映射到Java字段的其他字段的名称。@JsonAlias 注解中的值只用于反序列化。

@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:

现在我们已经添加了注释,让我们使用Jackson的ObjectMapper来使用Weather类创建Java对象。

@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

5.使用Gson

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

现在,让我们用Gson试试同样的方法。我们需要在@SerializedName注解中使用valuealternate参数。

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:

第一个将被用作默认值,而第二个将被用来表示我们想要映射的JSON字段的另一个名称。

@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

6.结论

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.

我们看到,通过使用Jackson的@JsonAlias或Gson的alternate参数,我们可以轻松地将不同的JSON格式转换为同一个Java对象。

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

你可以在GitHub上的JacksonGson项目中找到这些例子