This is my first spring project. I am trying to get weather from API (openweathermap), map it to dto and only if dto is unique insert to database.
At first idea was to use two dto classes. One for API response, another for database entity (with fewer fields). It worked pretty well, but I've heard about JSON annotations like @JsonIgnoreProperties(ignoreUnknown = true)
and @JsonProperty("name")
.
After some modifications to weatherSampleDto
it worked for API request, but not for entity ↔ dto
mapping anymore.
Weather API response:
{
"coord": {
"lon": 25.61,
"lat": 49.56
},
"weather": [
{
"id": 804,
"main": "Clouds",
"description": "хмарно",
"icon": "04n"
…
}
],
"base": "model",
"main": {
"temp": 1.06, <-------------- temperature
"feels_like": -2.27, <-------------- feelsLike
"temp_min": 1.06,
"temp_max": 1.06,
"pressure": 1016, <-------------- pressure
"humidity": 84, <-------------- humidity
"sea_level": 1016,
"grnd_level": 974
},
"wind": {
"speed": 1.65,
"deg": 281
},
"clouds": {
"all": 100 <-------------- clouds
},
"dt": 1580144397, <-------------- time
"sys": {
"country": "UA",
"sunrise": 1580104637,
"sunset": 1580137367
},
"timezone": 7200,
"id": 691650, <-------------- cityId
"name": "Ternopil", <-------------- cityName
"cod": 200
}
Here is WeatherSampleDto
after modification:
@JsonIgnoreProperties(ignoreUnknown = true)
public class WeatherSampleDto implements Serializable {
@JsonIgnore
private Long id;
@JsonProperty("name")
private String cityName;
private float temperature;
private float feelsLike;
private int pressure;
private int humidity;
private int clouds;
private int cityId;
@JsonProperty("dt")
private int time;
@JsonProperty("main")
private void unpackMain(Map<String, String> main) {
temperature = Float.parseFloat(main.get("temp"));
feelsLike = Float.parseFloat(main.get("feels_like"));
pressure = Integer.parseInt(main.get("pressure"));
humidity = Integer.parseInt(main.get("humidity"));
}
@JsonProperty("clouds")
private void unpackClouds(Map<String, Integer> cloudsObj) {
clouds = cloudsObj.get("all");
}
@JsonProperty("id")
private void unpackId(Integer idObj){
cityId = idObj;
}
...
And WeatherSample
entity:
@Entity
public class WeatherSample {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String cityName;
private float temperature;
private float feelsLike;
private int pressure;
private int humidity;
private int clouds;
private int cityId;
private int time;
...
It fails on each annotated field.
Such as com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.util.LinkedHashMap<java.lang.Object,java.lang.Object>`out of VALUE_NUMBER_INT token
at [Source: UNKNOWN; line: -1, column: -1] (through reference chain: weather.dto.WeatherSampleDto["clouds"])
Is it possible to solve with one dto class? If so how?
Common implementation would be creating @Service
class that gets the weather data from the API and the response model would be its own separate class then you take whatever data you need and fill the @Entity
class with it then store it.