Skip to content

Commit

Permalink
Fixed #936
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed Oct 21, 2015
1 parent d0da14d commit f73cd92
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 10 deletions.
2 changes: 2 additions & 0 deletions release-notes/VERSION
Expand Up @@ -12,6 +12,8 @@ Project: jackson-databind
#918: Add `MapperFeature.ALLOW_EXPLICIT_PROPERTY_RENAMING`
(contributed by David H)
#933: Close some gaps to allow using the tryToResolveUnresolved flows
#936: Deserialization into List subtype with JsonCreator no longer works
(reported by adamjoeldavis@github)
#948: Support leap seconds, any number of millisecond digits for ISO-8601 Dates.
(contributed by Jesse W)
#957: Merge `datatype-jdk7` stuff in (java.nio.file.Path handling)
Expand Down
53 changes: 46 additions & 7 deletions src/main/java/com/fasterxml/jackson/databind/type/TypeFactory.java
Expand Up @@ -301,10 +301,47 @@ protected Class<?> _findPrimitive(String className)
public JavaType constructSpecializedType(JavaType baseType, Class<?> subclass)
{
// simple optimization to avoid costly introspection if type-erased type does NOT differ
if (baseType.getRawClass() == subclass) {
final Class<?> rawBase = baseType.getRawClass();
if (rawBase == subclass) {
return baseType;
}

JavaType newType;

// also: if we start from untyped, not much to save
if (rawBase == Object.class) {
newType = _fromClass(null, subclass, TypeBindings.emptyBindings());
} else {
if (!rawBase.isAssignableFrom(subclass)) {
throw new IllegalArgumentException("Class "+subclass.getName()+" not subtype of "+baseType);
}

// 20-Oct-2015, tatu: Container, Map-types somewhat special. There is
// a way to fully resolve and merge hierarchies; but that gets expensive
// so let's, for now, try to create close-enough approximation that
// is not 100% same, structurally, but has equivalent information for
// our specific neeeds.
if (baseType.isInterface()) {
newType = baseType.refine(subclass, TypeBindings.emptyBindings(), null,
new JavaType[] { baseType });
} else {
newType = baseType.refine(subclass, TypeBindings.emptyBindings(), baseType,
NO_TYPES);
}
// Only SimpleType returns null, but if so just resolve regularly
if (newType == null) {
// But otherwise gets bit tricky, as we need to partially resolve the type hierarchy
// (hopefully passing null Class for root is ok)
newType = _fromClass(null, subclass, TypeBindings.emptyBindings());
}
}
// except possibly handlers
// newType = newType.withHandlersFrom(baseType);
return newType;

// 20-Oct-2015, tatu: Old simplistic approach

/*
// Currently mostly SimpleType instances can become something else
if (baseType instanceof SimpleType) {
// and only if subclass is an array, Collection or Map
Expand Down Expand Up @@ -345,6 +382,7 @@ public JavaType constructSpecializedType(JavaType baseType, Class<?> subclass)
// otherwise regular narrowing should work just fine
return baseType.narrowBy(subclass);
*/
}

/**
Expand Down Expand Up @@ -725,7 +763,7 @@ public JavaType constructParametricType(Class<?> rawType, JavaType... parameterT
}

/**
* @since 2.5 -- but probably deprecated in 2.7 or 2.8 (not needed with 2.7)
* @since 2.5 -- but will probably deprecated in 2.7 or 2.8 (not needed with 2.7)
*/
public JavaType constructParametrizedType(Class<?> parametrized, Class<?> parametersFor,
JavaType... parameterTypes)
Expand All @@ -734,7 +772,7 @@ public JavaType constructParametrizedType(Class<?> parametrized, Class<?> parame
}

/**
* @since 2.5 -- but probably deprecated in 2.7 or 2.8 (not needed with 2.7)
* @since 2.5 -- but will probably deprecated in 2.7 or 2.8 (not needed with 2.7)
*/
public JavaType constructParametrizedType(Class<?> parametrized, Class<?> parametersFor,
Class<?>... parameterClasses)
Expand Down Expand Up @@ -1078,7 +1116,7 @@ else if (superClass != null) {
context.resolveSelfReferences(result);

if (key != null) {
_typeCache.put(key, result); // cache object syncs
_typeCache.putIfAbsent(key, result); // cache object syncs
}
return result;
}
Expand Down Expand Up @@ -1151,16 +1189,17 @@ protected JavaType _fromWellKnownInterface(ClassStack context, Class<?> rawType,
protected JavaType _fromParamType(ClassStack context, ParameterizedType ptype,
TypeBindings parentBindings)
{
// 20-Oct-2015, tatu: Assumption here is we'll always get Class, not one of other Types
Class<?> rawType = (Class<?>) ptype.getRawType();

// First: what is the actual base type? One odd thing is that 'getRawType'
// returns Type, not Class<?> as one might expect. But let's assume it is
// always of type Class: if not, need to add more code to resolve it to Class.
Type[] args = ptype.getActualTypeArguments();
int paramCount = (args == null) ? 0 : args.length;
JavaType[] pt;
Class<?> rawType = (Class<?>) ptype.getRawType();

TypeBindings newBindings;

if (paramCount == 0) {
newBindings = EMPTY_BINDINGS;
} else {
Expand Down
Expand Up @@ -276,7 +276,7 @@ public void testOverrideClassInvalid() throws Exception
("{ \"strings\" : [ ] }", BrokenCollectionHolder.class);
fail("Expected a failure, but got results: "+result);
} catch (JsonMappingException jme) {
verifyException(jme, "is not assignable to");
verifyException(jme, "not subtype of");
}
}

Expand Down
@@ -1,12 +1,12 @@
package com.fasterxml.jackson.failing;
package com.fasterxml.jackson.databind.type;

import java.util.*;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.databind.*;

// For [databind#936], losing parametric type information it seems
public class PolymorphicListTest936 extends BaseMapTest
public class PolymorphicList036Test extends BaseMapTest
{
// note: would prefer using CharSequence, but while abstract, that's deserialized
// just fine as ... String
Expand Down
Expand Up @@ -276,9 +276,15 @@ public void testCollectionTypesRefined()
assertEquals(Long.class, subtype.getContentType().getRawClass());

// but with refinement, should have non-null super class
// 20-Oct-2015, tatu: For now refinement does not faithfully replicate the
// structure, it only retains most important information. Here it means
// that actually existing super-classes are skipped, and only original
// type is linked as expected
/*
JavaType superType = subtype.getSuperClass();
assertNotNull(superType);
assertEquals(AbstractList.class, superType.getRawClass());
*/
}

/*
Expand Down Expand Up @@ -344,13 +350,20 @@ public void testMapTypesRefined()
assertEquals(Integer.class, subtype.getContentType().getContentType().getRawClass());

// but with refinement, should have non-null super class
// 20-Oct-2015, tatu: For now refinement does not faithfully replicate the
// structure, it only retains most important information. Here it means
// that actually existing super-classes are skipped, and only original
// type is linked as expected

/*
JavaType superType = subtype.getSuperClass();
assertNotNull(superType);
assertEquals(HashMap.class, superType.getRawClass());
// which also should have proper typing
assertEquals(String.class, superType.getKeyType().getRawClass());
assertEquals(List.class, superType.getContentType().getRawClass());
assertEquals(Integer.class, superType.getContentType().getContentType().getRawClass());
*/
}

public void testMapTypesRaw()
Expand Down

0 comments on commit f73cd92

Please sign in to comment.