2014-10-16 8 views
1

Объекта, который я ищу десериализацию из JSON выглядит следующим образом:Джексон: десериализации общего типа, который содержит список

public class TypedMemberDTO<T> { 

     private List<T> details; 
     private String type; 

     // Getters and setters 
    } 

Я знаю, что T может быть только один из двух реальных классов в зависимости от type значение атрибута.

Я видел примеры того, как десериализации списков с помощью objectMapper.readValue(json, objectMapper.getTypeFactory().collectionType(ArrayList.class, MyClass.class));

Однако, я не видел никаких примеров о том, как добиться того, что я ищу, чтобы сделать выше.

Может ли кто-нибудь указать мне в правильном направлении при десериализации моего класса?

В идеале я хочу, чтобы избежать какого-либо подхода, основанный на аннотацию, если это возможно

+0

Я не думаю, что это возможно (из-за стирания типа) –

ответ

3

Как @fge предложил в своем комментарии, вы можете использовать пользовательский десериализатор для достижения этой цели.

Предполагая, что type содержит полное имя класса элементов списка, следующий десериализатор будет делать работу:

public class TypedMemberDTODeserializer extends JsonDeserializer<TypedMemberDTO<?>> { 

    @Override 
    public TypedMemberDTO<?> deserialize(JsonParser jp, DeserializationContext ctxt) 
      throws IOException { 
     try { 
      JsonNode rootNode = jp.getCodec().readTree(jp); 
      String type = rootNode.get("type").asText(); 
      JavaType parametricListType = ctxt.getTypeFactory().constructParametricType(
        List.class, Class.forName(type)); 
      JsonNode detailsNode = rootNode.get("details"); 
      List<?> detailsList = new ObjectMapper().readValue(detailsNode.toString(), parametricListType); 
      return new TypedMemberDTO(detailsList, type); // unchecked 
     } catch (ClassNotFoundException e) { 
      throw new IOException(e); 
     } 

    } 
} 

В ObjectMapper должна быть проинформирован о десериализаторе:

 ObjectMapper objectMapper = new ObjectMapper(); 
     objectMapper.registerModule(new SimpleModule().addDeserializer(TypedMemberDTO.class, 
       new TypedMemberDTODeserializer())); 
     TypedMemberDTO<?> typedMemberDTO = objectMapper.readValue(jsonString, TypedMemberDTO.class); 

Я не знаю производительность этого решения (он использует встроенный ObjectMapper в десериализаторе), вам, возможно, придется это проверить. Вы можете узнать больше о пользовательских десериализаторах here.

Смежные вопросы