我查看了许多与此相关的问题,但我无法找到这个确切的用例。 这里假设我正在使用Java Jackson库。
我有以下类层次结构:
public class Event {
@JsonProperty("si")
String sessionId;
@JsonProperty("eventType")
String eventType;
...
}
@JsonSerialize(include= JsonSerialize.Inclusion.NON_NULL)
public class InitEvent extends Event
{
@JsonProperty("pm")
Params params;
public Params getParams()
{
return params;
}
.....
}
@JsonSerialize(include= JsonSerialize.Inclusion.NON_NULL)
public class RecoEvent extends Event
{
@JsonProperty("ti")
String targetId;
@JsonProperty("tt")
int targetType;
public String getTargetId()
{
return targetId;
}
....
}
反序列化的规则是:
如果eventType == 0则反序列化为InitEvent
如果eventType == 0则反序列化为RecoEvent
开箱即用的杰克逊反序列化将不起作用,因为它不知道要反序列化的类。处理它的一种方法是在基类上执行以下操作:
@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@class")
@JsonSerialize(include= JsonSerialize.Inclusion.NON_NULL)
public class Event
此解决方案的问题是假设客户端将使用相同的映射器进行序列化,因为@class元素现在需要存在于JSON中。
我的客户端不会在传入的JSON中发送额外的@class元素。
所需的解决方案是什么?
我如何编写一个自定义反序列化器,根据eventType值选择正确的派生类?
提前谢谢
答案 0 :(得分:2)
最后我必须编写自己的反序列化器。
这有两个步骤,首先实现自定义反序列化器,然后注册它。
实施如下:
public class EvtListDeserializer extends JsonDeserializer<EventList>
{
private static ObjectMapper mapper = new ObjectMapper();
@Override
public EventList deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException, JsonProcessingException
{
EventList eventList = new EventList();
List<Event> listOfEvents = new ArrayList<Event>();
ObjectCodec oc = jsonParser.getCodec();
JsonNode eventListNode = oc.readTree(jsonParser);
ArrayNode node = (ArrayNode) eventListNode.get("evt");
Iterator<JsonNode> events = node.elements();
for (; events.hasNext(); )
{
JsonNode eventNode = events.next();
int eventType = eventNode.get("type").asInt();
Event event;
if (eventType == EventTypes.MoveEvent.getValue())
{
event = mapper.readValue(eventNode.toString(), MoveEvent.class);
}
else if (eventType == EventTypes.CopyEvent.getValue())
{
event = mapper.readValue(eventNode.toString(), CopyEvent.class);
}
else
{
throw new InvalidEventTypeException("Invalid event type:" + eventType);
}
listOfEvents.add(event);
}
eventList.setEvents(listOfEvents);
return eventList;
}
}
然后,您只需在使用映射器的类中注册如下:
public void init()
{
SimpleModule usageModule = new SimpleModule().addDeserializer(EventList.class, new EvtListDeserializer());
mapper.registerModule(usageModule);
}
完美无缺。