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?
Advertisement
Answer
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" : [ ] }