如何通过 Jackson 的注释定义通用列表反序列化器? [英] How to define a generic list deserializer through annotations with Jackson?
问题描述
假设我有一个具有列表属性的对象:
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;
}
}
我正在寻找一种创建通用"反序列化器的方法——一种能够反序列化两种类型列表的方法,类似于 ContextualDeserializer 用于使用 Jackson 将 JSON 映射到不同类型的地图.
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.
最终目的是在 MyListDeserializer
中实现自定义反序列化逻辑,将空字符串 ""
反序列化为空列表,但我想了解一个通用方法,不只是空字符串.
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.
推荐答案
您可以指定用于反序列化列表元素的反序列化器类使用 @JsonDeserializer
注释的 contentUsing
属性.
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;
}
}
使您的解串器扩展 JsonDeserializer
并在 BaseClass 中有一个属性来存储具体类的实际类型.
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
}
}
}
或者,如果您想为没有公共基类的所有 List 类型使用单个反序列化器,则使用 using
属性,让 MyListDeserializer
扩展 JsonDeserialize
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)
}
}
这篇关于如何通过 Jackson 的注释定义通用列表反序列化器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!