/**
  * Helper method that will check whether given annotated entity (usually class, but may also be a
  * property accessor) indicates that a {@link Converter} is to be used; and if so, to construct
  * and return suitable serializer for it. If not, will simply return given serializer as is.
  */
 protected JsonDeserializer<Object> findConvertingDeserializer(
     DeserializationContext ctxt, Annotated a, JsonDeserializer<Object> deser)
     throws JsonMappingException {
   Converter<Object, Object> conv = findConverter(ctxt, a);
   if (conv == null) {
     return deser;
   }
   JavaType delegateType = conv.getInputType(ctxt.getTypeFactory());
   return (JsonDeserializer<Object>)
       new StdDelegatingDeserializer<Object>(conv, delegateType, deser);
 }
  /**
   * Method that does the heavy lifting of checking for per-type annotations, find out full type,
   * and figure out which actual factory method to call.
   */
  @SuppressWarnings("unchecked")
  protected JsonDeserializer<Object> _createDeserializer(
      DeserializationContext ctxt, DeserializerFactory factory, JavaType type)
      throws JsonMappingException {
    final DeserializationConfig config = ctxt.getConfig();

    // First things first: do we need to use abstract type mapping?
    if (type.isAbstract() || type.isMapLikeType() || type.isCollectionLikeType()) {
      type = factory.mapAbstractType(config, type);
    }
    BeanDescription beanDesc = config.introspect(type);
    // Then: does type define explicit deserializer to use, with annotation(s)?
    JsonDeserializer<Object> deser = findDeserializerFromAnnotation(ctxt, beanDesc.getClassInfo());
    if (deser != null) {
      return deser;
    }

    // If not, may have further type-modification annotations to check:
    JavaType newType = modifyTypeByAnnotation(ctxt, beanDesc.getClassInfo(), type);
    if (newType != type) {
      type = newType;
      beanDesc = config.introspect(newType);
    }

    // We may also have a Builder type to consider...
    Class<?> builder = beanDesc.findPOJOBuilder();
    if (builder != null) {
      return (JsonDeserializer<Object>)
          factory.createBuilderBasedDeserializer(ctxt, type, beanDesc, builder);
    }

    // Or perhaps a Converter?
    Converter<Object, Object> conv = beanDesc.findDeserializationConverter();
    if (conv == null) { // nope, just construct in normal way
      return (JsonDeserializer<Object>) _createDeserializer2(ctxt, factory, type, beanDesc);
    }
    // otherwise need to do bit of introspection
    JavaType delegateType = conv.getInputType(ctxt.getTypeFactory());
    return new StdDelegatingDeserializer<Object>(
        conv, delegateType, _createDeserializer2(ctxt, factory, delegateType, beanDesc));
  }