java 如何通过 Jackson 的注释定义通用列表反序列化器?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12937197/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to define a generic list deserializer through annotations with Hymanson?
提问by ipavlic
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 Hymanson.
我正在寻找一种创建“通用”反序列化器的方法——一种能够反序列化两种类型列表的方法,类似于ContextualDeserializer 用于将 JSON 映射到不同类型的映射与 Hymanson。
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.
最终目的是实现自定义反序列化逻辑,MyListDeserializer
将空字符串反序列""
化为空列表,但我想知道一种通用方法,而不仅仅是空字符串。
回答by Sumit Jain
You can specify the deserializer class with which to deserialize the elements of the list
with the contentUsing
attribute of the @JsonDeserializer
annotation.
您可以指定反序列化器类,使用该类反序列化具有注释contentUsing
属性的列表元素@JsonDeserializer
。
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.
使您的反序列化器扩展JsonDeserializer<BaseClass>
并在 BaseClass 中有一个属性,用于存储具体类的实际类型。
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.
或者,如果您想要为没有公共基类的所有 List 类型使用单个反序列化器,则使用using
属性,具有MyListDeserializer
extend JsonDeserialize<Object>
。为了确定列表元素的类型,您必须编写一个自定义序列化程序,将类型信息添加到列表中,然后可以在通用反序列化程序中使用。
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)
}
}