2017-11-17 22 views
1

외부 시스템의 이유로 모든 Java Map으로 수신 될 수 있습니다. 클라이언트의 키 - 값 쌍이입니다. Map<String, Book>은 실제로 Json-serialized List<MapEntry<String, Book>>으로 수신됩니다. 이것은지도의 표현을 기대하기 위해 Json deserialization 프로세스를 사용자 정의해야한다는 것을 의미합니다.Jackson의 JsonDeserializer 내부에서 감지 된 제네릭 형식을 가져옵니다.

문제는 JsonDeserializer 날이 역 직렬화하기로했다 감지 된 제네릭 형식 (위의 예에서 Map<String, Book>)에 액세스 할 수 없습니다

deserialize(JsonParser p, DeserializationContext ctxt) 

방법을 구현할 수 있다는 것입니다. 그 정보가 없으면 유형 안전을 잃지 않고 List<MapEntry<String, Book>>을 역 직렬화 할 수 없습니다.

나는 Converter을보고 있었지만 상황은 훨씬 적습니다.

예.

public Map<K,V> convert(List<MapToListTypeAdapter.MapEntry<K,V>> list) { 
    Map<K,V> x = new HashMap<>(); 
    list.forEach(entry -> x.put(entry.getKey(), entry.getValue())); 
    return x; 
} 

그러나 유형을 확인 할 수있는 방법이 없기 때문에이 잠재적으로, 검색에 ClassCastException 발생합니다 위험지도를 만들 것입니다 실제로 합리적이다. 이 문제를 해결할 방법이 있습니까? 내가 기대했던 것의 예를 들어

는 GSON의 JsonDeserializer은 다음과 같습니다

T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) 

즉, 예상되는 유형에 정상적으로 액세스 할 수 있습니다.

답변

0

저자에게서 직접 Jackson Google group에 대한 답변을 얻었습니다.

이해해야 할 중요한 사항은 JsonDeserializer이 (가)으로 작성되고 상황에 맞게 작성되고 그 순간에만 전체 유형 및 기타 정보가 수신된다는 것입니다. 이 정보를 얻으려면 디시리얼라이저가 ContextualDeserializer을 구현해야합니다. 그 createContextual 메서드는 디시리얼라이저 인스턴스를 초기화하기 위해 호출되며 에 액세스 할 수 있으며 전체는 JavaType입니다.

그래서 결국 같은 것을 볼 수 있었다 :

public class MapDeserializer extends JsonDeserializer implements ContextualDeserializer { 

    private JavaType type; 

    public MapDeserializer() { 
    } 

    public MapDeserializer(JavaType type) { 
     this.type = type; 
    } 

    @Override 
    public JsonDeserializer<?> createContextual(DeserializationContext deserializationContext, BeanProperty beanProperty) throws JsonMappingException { 
     //beanProperty is null when the type to deserialize is the top-level type or a generic type, not a type of a bean property 
     JavaType type = deserializationContext.getContextualType() != null 
      ? deserializationContext.getContextualType() 
      : beanProperty.getMember().getType();    
     return new MapDeserializer(type); 
    } 

    @Override 
    public Map deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { 
     //use this.type as needed 
    } 

    ... 
} 

등록 정상적으로 사용을 :

ObjectMapper mapper = new ObjectMapper(); 
SimpleModule module = new SimpleModule(); 
module.addDeserializer(Map.class, new MapDeserializer()); 
mapper.registerModule(module);