如何通过 Jackson 的注释定义通用列表反序列化器? [英] How to define a generic list deserializer through annotations with Jackson?

查看:21
本文介绍了如何通过 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆