Implemented #148
diff --git a/release-notes/VERSION b/release-notes/VERSION
index 777e87f..68d2115 100644
--- a/release-notes/VERSION
+++ b/release-notes/VERSION
@@ -25,6 +25,9 @@
 * [Issue#140]: Add 'SerializationFeature.WRITE_BIGDECIMAL_AS_PLAIN' to allow forcing
   of non-scientific notation when serializing BigDecimals.
  (suggested by phedny@github)
+* [Issue#148]: Add 'DeserializationFeature.FAIL_ON_INVALID_SUBTYPE`, which allows mapping
+  entries with missing or invalid type id into null references (instead of failing).
+  Also allows use of '@JsonTypeInfo.defaultImpl = NoClass.class' as alternative.
 * [Issue#159]: Add more accessors in 'MappingIterator': getParser(), getParserSchema(),
   readAll()
  (suggested by Tom D)
diff --git a/src/main/java/com/fasterxml/jackson/databind/DeserializationFeature.java b/src/main/java/com/fasterxml/jackson/databind/DeserializationFeature.java
index 53aabf1..2de1164 100644
--- a/src/main/java/com/fasterxml/jackson/databind/DeserializationFeature.java
+++ b/src/main/java/com/fasterxml/jackson/databind/DeserializationFeature.java
@@ -128,6 +128,19 @@
     FAIL_ON_NUMBERS_FOR_ENUMS(false),
 
     /**
+     * Feature that determines what happens when type of a polymorphic
+     * value (indicated for example by {@link com.fasterxml.jackson.annotation.JsonTypeInfo})
+     * can not be found (missing) or resolved (invalid class name, unmappable id);
+     * if enabled, an exception ir thrown; if false, null value is used instead.
+     *<p>
+     * Feature is enabled by default so that exception is thrown for missing or invalid
+     * type information.
+     * 
+     * @since 2.2
+     */
+    FAIL_ON_INVALID_SUBTYPE(true),
+    
+    /**
      * Feature that determines whether Jackson code should catch
      * and wrap {@link Exception}s (but never {@link Error}s!)
      * to add additional information about
diff --git a/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java b/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java
index bd430e4..2a0c196 100644
--- a/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java
+++ b/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java
@@ -20,7 +20,6 @@
 import com.fasterxml.jackson.databind.deser.*;
 import com.fasterxml.jackson.databind.introspect.*;
 import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
-import com.fasterxml.jackson.databind.jsonschema.JsonSchema;
 import com.fasterxml.jackson.databind.jsontype.*;
 import com.fasterxml.jackson.databind.jsontype.impl.StdSubtypeResolver;
 import com.fasterxml.jackson.databind.jsontype.impl.StdTypeResolverBuilder;
@@ -2542,7 +2541,8 @@
      * @return Constructed JSON schema.
      */
     @SuppressWarnings("deprecation")
-    public JsonSchema generateJsonSchema(Class<?> t) throws JsonMappingException {
+    public com.fasterxml.jackson.databind.jsonschema.JsonSchema generateJsonSchema(Class<?> t)
+            throws JsonMappingException {
         return _serializerProvider(getSerializationConfig()).generateJsonSchema(t);
     }
 
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/NullifyingDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/NullifyingDeserializer.java
new file mode 100644
index 0000000..196a1c5
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/NullifyingDeserializer.java
@@ -0,0 +1,55 @@
+package com.fasterxml.jackson.databind.deser.std;
+
+import java.io.IOException;
+
+import com.fasterxml.jackson.core.*;
+import com.fasterxml.jackson.databind.*;
+import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
+
+/**
+ * Bogus deserializer that will simply skip all content there is to map
+ * and returns Java null reference.
+ * 
+ * @since 2.2
+ */
+public class NullifyingDeserializer
+    extends StdDeserializer<Object>
+{
+    private static final long serialVersionUID = 1L;
+
+    public final static NullifyingDeserializer instance = new NullifyingDeserializer();
+    
+    public NullifyingDeserializer() { super(Object.class); }
+
+    /*
+    /**********************************************************
+    /* Deserializer API
+    /**********************************************************
+     */
+    
+    @Override
+    public Object deserialize(JsonParser jp, DeserializationContext ctxt)
+        throws IOException, JsonProcessingException
+    {
+        jp.skipChildren();
+        return null;
+    }
+
+    @Override
+    public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt,
+            TypeDeserializer typeDeserializer)
+        throws IOException, JsonProcessingException
+    {
+        // Not sure if we need to bother but:
+
+        JsonToken t = jp.getCurrentToken();
+        switch (t) {
+        case START_ARRAY:
+        case START_OBJECT:
+        case FIELD_NAME:
+            return typeDeserializer.deserializeTypedFromAny(jp, ctxt);
+        default:
+            return null;
+        }
+    }
+}
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsPropertyTypeDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsPropertyTypeDeserializer.java
index cab8d52..84a25a0 100644
--- a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsPropertyTypeDeserializer.java
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/AsPropertyTypeDeserializer.java
@@ -119,8 +119,8 @@
         throws IOException, JsonProcessingException
     {
         // As per [JACKSON-614], may have default implementation to use
-        if (_defaultImpl != null) { 
-            JsonDeserializer<Object> deser = _findDefaultImplDeserializer(ctxt);
+        JsonDeserializer<Object> deser = _findDefaultImplDeserializer(ctxt);
+        if (deser != null) {
             if (tb != null) {
                 tb.writeEndObject();
                 jp = tb.asParser(jp);
diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeDeserializerBase.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeDeserializerBase.java
index 76b4ac5..30a84e6 100644
--- a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeDeserializerBase.java
+++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/TypeDeserializerBase.java
@@ -8,8 +8,11 @@
 
 import com.fasterxml.jackson.databind.BeanProperty;
 import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.DeserializationFeature;
 import com.fasterxml.jackson.databind.JavaType;
 import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.annotation.NoClass;
+import com.fasterxml.jackson.databind.deser.std.NullifyingDeserializer;
 import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
 import com.fasterxml.jackson.databind.jsontype.TypeIdResolver;
 
@@ -21,7 +24,7 @@
     implements java.io.Serializable
 {
     private static final long serialVersionUID = 278445030337366675L;
-
+    
     protected final TypeIdResolver _idResolver;
     
     protected final JavaType _baseType;
@@ -178,9 +181,20 @@
     protected final JsonDeserializer<Object> _findDefaultImplDeserializer(DeserializationContext ctxt)
         throws IOException, JsonProcessingException
     {
+        /* 06-Feb-2013, tatu: As per [Issue#148], consider default implementation value of
+         *   {@link NoClass} to mean "serialize as null"; as well as DeserializationFeature
+         *   to do swift mapping to null
+         */
         if (_defaultImpl == null) {
+            if (!ctxt.isEnabled(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE)) {
+                return NullifyingDeserializer.instance;
+            }
             return null;
         }
+        if (_defaultImpl.getRawClass() == NoClass.class) {
+            return NullifyingDeserializer.instance;
+        }
+        
         synchronized (_defaultImpl) {
             if (_defaultImplDeserializer == null) {
                 _defaultImplDeserializer = ctxt.findContextualValueDeserializer(
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedDeserializationWithDefault.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedDeserializationWithDefault.java
index d9d3651..f651c42 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedDeserializationWithDefault.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestTypedDeserializationWithDefault.java
@@ -4,6 +4,9 @@
 
 import com.fasterxml.jackson.annotation.*;
 import com.fasterxml.jackson.databind.BaseMapTest;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.annotation.NoClass;
 
 /**
  * Unit tests related to [JACKSON-712]; specialized handling of
@@ -39,12 +42,20 @@
         }
     }
 
+    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type",
+            defaultImpl = NoClass.class)
+    public static class DefaultWithNoClass { }
+
+    // and then one with no defaultImpl nor listed subtypes
+    @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
+    abstract static class MysteryPolymorphic { }
+    
     /*
     /**********************************************************
     /* Unit tests, deserialization
     /**********************************************************
      */
-
+    
     public void testDeserializationWithObject() throws Exception
     {
         Inter inter = objectReader(Inter.class).readValue("{\"type\": \"mine\", \"blah\": [\"a\", \"b\", \"c\"]}");
@@ -73,4 +84,24 @@
         assertTrue(inter instanceof LegacyInter);
         assertEquals(Arrays.asList("a", "b"), ((MyInter) inter).blah);
     }
+
+    // [Issue#148]
+    public void testDefaultAsNoClass() throws Exception
+    {
+        Object ob = objectReader(DefaultWithNoClass.class).readValue("{ }");
+        assertNull(ob);
+        ob = objectReader(DefaultWithNoClass.class).readValue("{ \"bogus\":3 }");
+        assertNull(ob);
+    }
+
+    // [Issue#148]
+    public void testBadTypeAsNull() throws Exception
+    {
+        ObjectMapper mapper = new ObjectMapper();
+        mapper.disable(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE);
+        Object ob = mapper.readValue("{}", MysteryPolymorphic.class);
+        assertNull(ob);
+        ob = mapper.readValue("{ \"whatever\":13}", MysteryPolymorphic.class);
+        assertNull(ob);
+    }
 }