«1. Обзор

В этом руководстве мы увидим, как использовать Jackson и Gson для сопоставления разных полей JSON с одним полем Java.

2. Зависимости Maven

Чтобы использовать библиотеки Jackson и Gson, нам нужно добавить в наш 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. Пример JSON

Давайте представим, что мы хотим получить подробности о погоде для разных мест в наше Java-приложение. Мы нашли несколько веб-сайтов, которые публикуют данные о погоде в виде документов JSON. Однако они используют немного разные форматы:

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

И:

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

Мы хотим десериализовать оба этих формата в один и тот же класс Java с именем Weather:

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

Итак, давайте посмотрим как мы можем добиться этого, используя библиотеки Джексона и Гсона.

4. Использование Джексона

Для этого мы будем использовать аннотации Джексона @JsonProperty и @JsonAlias. Это позволит нам сопоставить более одного свойства JSON с одним и тем же полем Java.

Во-первых, мы собираемся использовать аннотацию @JsonProperty, чтобы Джексон знал имя поля JSON для сопоставления. Значение в аннотации @JsonProperty используется как для десериализации, так и для сериализации.

Тогда мы можем использовать аннотацию @JsonAlias. В результате Джексон узнает имена других полей в документе JSON, которые сопоставляются с полем Java. Значение в аннотации @JsonAlias ​​используется только для десериализации:

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

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

Теперь, когда мы добавили аннотации, давайте воспользуемся ObjectMapper Джексона для создания объектов Java с помощью класса Weather:

@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. Использование Gson

Теперь попробуем то же самое с Gson. Нам нужно будет использовать значение и альтернативные параметры в аннотации @SerializedName.

Первый будет использоваться по умолчанию, а второй будет использоваться для указания альтернативного имени поля 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;

Теперь, когда мы добавили аннотации, давайте протестируйте наш пример:

@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. Заключение

Мы видели, что, используя либо @JsonAlias ​​Джексона, либо альтернативный параметр Gson, мы можем легко преобразовывать различные форматы JSON в один и тот же объект Java.

Вы найдете примеры в проектах Джексона и Гсона на GitHub.