I have a vehicle
Java class defined like this:
public final class Vehicle {
private Integer id;
private String description;
private Location start;
private Location end;
private List<Integer> capacity;
private List<Integer> skills;
private TimeWindow timeWindow;
private List<Break> breaks;
public Vehicle(Integer id, String description, Location start,
Location end, List<Integer> capacity,
List<Integer> skills, TimeWindow timeWindow,
List<Break> breaks) {
this.id = id;
this.description = description;
this.start = start;
this.end = end;
this.capacity = capacity;
this.skills = skills;
this.timeWindow = timeWindow;
this.breaks = breaks;
}
TimeWindow
is defined like this:
public final class Location {
private final Double latitude;
private final Double longitude;
public Location(Double latitude, Double longitude) {
this.latitude = latitude;
this.longitude = longitude;
}
Now, the JSON I am getting, does not define latitude
and longitude
for the location (start
and end
); this information is encoded as just an array, see e.g.:
// vehicle.json
{
"id" : 0,
"description" : "vehicle 0",
"start" : [
12.304373066846503,
51.62270653765847
],
"end" : [
12.304373066846503,
51.62270653765847
],
"capacity" : [
9
],
"skills" : [
],
"time_window" : [
1644188400,
1644274800
],
"breaks" : [
]
}
How can I write a custom deserializer for just Location
(same problem with TimeWindow
) in that case? If possible, I do not want to write a custom deserializer for the whole Vehicle
class.
I tried this:
@JsonDeserialize(
using = LocationJsonDeserializer.class
)
public final class Location {
// ....
public class LocationJsonDeserializer extends JsonDeserializer<Location> {
@Override
public Location deserialize(JsonParser p, DeserializationContext ctxt) {
final var longitude = 0d;
final var latitude = 0d;
// what to do here?
return new Location(latitude, longitude);
}
It seems to me, that I am getting the whole Vehicle
passed into my deserialize
method, not just the Location
part. Am I doing something wrong here? Is this approach feasible using Jackson?
CodePudding user response:
You can add a constructor to Vehicle
class using @JsonCreator
tag and a Double[]
for parameters start
and end
. You also need to add @JsonProperty
tag to each parameter.
Here's an example, for simplicity I didn't include parameters time_window
and breaks
.
@JsonCreator
public Vehicle(@JsonProperty("id") Integer id,
@JsonProperty("description") String description,
@JsonProperty("start") Double[] start,
@JsonProperty("end") Double[] end,
@JsonProperty("capacity") List<Integer> capacity,
@JsonProperty("skills") List<Integer> skills) {
this(id, description, new Location(start[0], start[1]),
new Location(end[0], end[1]), capacity, skills);
}
Test using the json
in the question without parameters time_window
and breaks
:
String result = "{\"id\":0,\"description\":\"vehicle 0\",\"start\":[12.304373066846503,51.62270653765847],\"end\":[12.304373066846503,51.62270653765847],\"capacity\":[9],\"skills\":[]}";
ObjectMapper mapper = new ObjectMapper();
Vehicle vehicle = mapper.readValue(result, Vehicle.class);
String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(vehicle);
System.out.println(json);
Output:
{
"id" : 0,
"description" : "vehicle 0",
"start" : {
"latitude" : 12.304373066846503,
"longitude" : 51.62270653765847
},
"end" : {
"latitude" : 12.304373066846503,
"longitude" : 51.62270653765847
},
"capacity" : [ 9 ],
"skills" : [ ]
}