Mapeando vários campos JSON para um único campo Java
1. Visão geral
Neste tutorial, veremos como usar Jackson e Gson para mapear diferentes campos JSON em um único campo Java.
2. Dependências do Maven
3. JSON de amostra
Vamos imaginar que desejamos obter os detalhes do clima para diferentes locais em nosso aplicativo Java. Encontramos alguns sites que publicam dados meteorológicos como documentos JSON. No entanto, eles usam formatos ligeiramente diferentes:
{
"location": "London",
"temp": 15,
"weather": "Cloudy"
}
And:
{
"place": "Lisbon",
"temperature": 35,
"outlook": "Sunny"
}
Queremos desserializar esses dois formatos na mesma classe Java, chamadaWeather:
public class Weather {
private String location;
private int temp;
private String outlook;
}
Então, vamos dar uma olhada em como podemos conseguir isso usando as bibliotecas Jackson e Gson.
4. Usando 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.
Primeiro, vamos usar a anotação@JsonProperty, para que Jackson saiba o nome do campo JSON a mapear. O valor na anotação@JsonProperty é usado para desserializar e serializar.
Então podemos usar a anotação@JsonAlias. Como resultado, Jackson saberá os nomes de outros campos no documento JSON que são mapeados para o campo Java. O valor na anotação@JsonAlias é usado apenas para desserializar:
@JsonProperty("location")
@JsonAlias("place")
private String location;
@JsonProperty("temp")
@JsonAlias("temperature")
private int temp;
@JsonProperty("outlook")
@JsonAlias("weather")
private String outlook;
Agora que adicionamos as anotações, vamos usarObjectMapper de Jackson para criar objetos Java usando a classeWeather:
@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. Usando o Gson
Agora, vamos tentar o mesmo com Gson. Precisaremos usar os parâmetrosvalueealternate na anotação@SerializedName.
O primeiro será usado como padrão, enquanto o segundo será usado para indicar um nome alternativo do campo JSON que queremos mapear:
@SerializedName(value="location", alternate="place")
private String location;
@SerializedName(value="temp", alternate="temperature")
private int temp;
@SerializedName(value="outlook", alternate="weather")
private String outlook;
Agora que adicionamos as anotações, vamos testar nosso exemplo:
@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. Conclusão
Vimos que usando o parâmetro@JsonAlias de Jackson oualternate de Gson, podemos facilmente converter diferentes formatos JSON no mesmo objeto Java.
Você encontrará os exemplos emJacksoneGson projects on GitHub.