Let's say I have an object which has list properties:
public class Citizen {
name
List<Tickets> tickets
List<Fines> fines
}
I'd like to define a generic custom deserializer for lists through annotations:
public class Citizen {
...
@JsonDeserializer(MyListDeserializer<Tickets>) // <-- generic deserializer
public void setTickets(List<Tickets> tickets) {
this.tickets = tickets;
}
@JsonDeserializer(MyListDeserializer<Fines>) // <-- how can I do that?
public void setFines(List<Fines> fines) {
this.fines = fines;
}
}
I'm looking for a way to create a "generic" deserializer — one that would be able to deserialize both types of lists, similar to ContextualDeserializer for mapping JSON to different types of maps with Jackson .
The final purpose is to implement custom deserializing logic in MyListDeserializer
to deserialize empty strings ""
as empty lists, but I'd like to know about a general approach, not just for empty strings.
You can specify the deserializer class with which to deserialize the elements of the list with the contentUsing
attribute of the @JsonDeserializer
annotation.
public class Citizen {
...
@JsonDeserializer(contentUsing=MyListDeserializer.class)
public void setTickets(List<Tickets> tickets) {
this.tickets = tickets;
}
}
Make your deserializer extend JsonDeserializer<BaseClass>
and have a attribute in the BaseClass that stores the actual type of the concrete class.
abstract class BaseTickets {
String ticketType;
public String getTicketType()
}
public class MyListDeserializer extends JsonDeserializer<BaseTickets> {
@Override
public BaseTickets deserialize(JsonParser jsonParser, DeserializationContext arg1) throws IOException, JsonProcessingException {
ObjectCodec oc = jsonParser.getCodec();
JsonNode node = oc.readTree(jsonParser);
Iterator<JsonNode> elements = node.getElements();
for (; elements.hasNext();) {
String type = (String) elements.next().get("ticketType");
if (type.equals()){
//create concrete type here
}
}
}
Or if you want a single deserializer for all List types with no common base class, then use the using
attribute, have MyListDeserializer
extend JsonDeserialize<Object>
. For determining the type of list element you would have to write a custom serializer that adds the type information to the list which can then be used in the generic deserializer.
public class Citizen {
...
@JsonDeserializer(using=MyListDeserializer.class)
@JsonSerializer(using=MyListSerializer.class)
public void setTickets(List<Tickets> tickets) {
this.tickets = tickets;
}
}
public class MyListSerializer extends JsonSerializer<Object> {
@Override
public void serialize(Object list, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
@SuppressWarnings("rawtypes")
jgen.writeStartObject();
String type = getListType(list);
jgen.writeStringField("listType", type);
jgen.writeObjectField("list", list)
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.