1616public class ClassNameIdResolver
1717 extends TypeIdResolverBase
1818{
19+ private final static String JAVA_UTIL_PKG = "java.util." ;
20+
1921 public ClassNameIdResolver (JavaType baseType , TypeFactory typeFactory ) {
2022 super (baseType , typeFactory );
2123 }
@@ -86,8 +88,8 @@ protected JavaType _typeFromId(String id, DatabindContext ctxt) throws IOExcepti
8688 /* Internal methods
8789 /**********************************************************
8890 */
89-
90- protected final String _idFrom (Object value , Class <?> cls , TypeFactory typeFactory )
91+
92+ protected String _idFrom (Object value , Class <?> cls , TypeFactory typeFactory )
9193 {
9294 // Need to ensure that "enum subtypes" work too
9395 if (Enum .class .isAssignableFrom (cls )) {
@@ -96,8 +98,8 @@ protected final String _idFrom(Object value, Class<?> cls, TypeFactory typeFacto
9698 }
9799 }
98100 String str = cls .getName ();
99- if (str .startsWith ("java.util" )) {
100- // 25-Jan-2009, tatu: There are some internal classes that we can not access as is.
101+ if (str .startsWith (JAVA_UTIL_PKG )) {
102+ // 25-Jan-2009, tatu: There are some internal classes that we cannot access as is.
101103 // We need better mechanism; for now this has to do...
102104
103105 // Enum sets and maps are problematic since we MUST know type of
@@ -113,20 +115,20 @@ protected final String _idFrom(Object value, Class<?> cls, TypeFactory typeFacto
113115 // not optimal: but EnumMap is not a customizable type so this is sort of ok
114116 str = typeFactory .constructMapType (EnumMap .class , enumClass , valueClass ).toCanonical ();
115117 } else {
116- String end = str . substring ( 9 );
117- if (( end . startsWith ( ".Arrays$" ) || end . startsWith ( ".Collections$" ))
118- && str . indexOf ( "List" ) >= 0 ) {
119- /* 17-Feb-2010, tatus: Another such case: result of
120- * Arrays.asList() is named like so in Sun JDK...
121- * Let's just plain old ArrayList in its place
122- * NOTE: chances are there are plenty of similar cases
123- * for other wrappers... (immutable, singleton, synced etc)
124- */
125- str = "java.util.ArrayList" ;
118+ // 17-Feb-2010, tatus: Another such case: result of Arrays.asList() is
119+ // named like so in Sun JDK... Let's just plain old ArrayList in its place.
120+ // ... also, other similar cases exist...
121+ String suffix = str . substring ( JAVA_UTIL_PKG . length ());
122+ if ( isJavaUtilCollectionClass ( suffix , "List" )) {
123+ str = ArrayList . class . getName ();
124+ } else if ( isJavaUtilCollectionClass ( suffix , "Map" )){
125+ str = HashMap . class . getName ();
126+ } else if ( isJavaUtilCollectionClass ( suffix , "Set" )){
127+ str = HashSet . class . getName () ;
126128 }
127129 }
128130 } else if (str .indexOf ('$' ) >= 0 ) {
129- /* Other special handling may be needed for inner classes, [JACKSON-584].
131+ /* Other special handling may be needed for inner classes,
130132 * The best way to handle would be to find 'hidden' constructor; pass parent
131133 * value etc (which is actually done for non-anonymous static classes!),
132134 * but that is just not possible due to various things. So, we will instead
@@ -135,10 +137,8 @@ protected final String _idFrom(Object value, Class<?> cls, TypeFactory typeFacto
135137 */
136138 Class <?> outer = ClassUtil .getOuterClass (cls );
137139 if (outer != null ) {
138- /* one more check: let's actually not worry if the declared
139- * static type is non-static as well; if so, deserializer does
140- * have a chance at figuring it all out.
141- */
140+ // one more check: let's actually not worry if the declared static type is
141+ // non-static as well; if so, deserializer does have a chance at figuring it all out.
142142 Class <?> staticType = _baseType .getRawClass ();
143143 if (ClassUtil .getOuterClass (staticType ) == null ) {
144144 // Is this always correct? Seems like it should be...
@@ -154,4 +154,17 @@ protected final String _idFrom(Object value, Class<?> cls, TypeFactory typeFacto
154154 public String getDescForKnownTypeIds () {
155155 return "class name used as type id" ;
156156 }
157+
158+ private static boolean isJavaUtilCollectionClass (String clz , String type )
159+ {
160+ if (clz .startsWith ("Collections$" )) {
161+ // 02-Jan-2017, tatu: As per [databind#1868], may need to leave Unmodifiable variants as is
162+ return (clz .indexOf (type ) > 0 )
163+ && !clz .contains ("Unmodifiable" );
164+ }
165+ if (clz .startsWith ("Arrays$" )) {
166+ return (clz .indexOf (type ) > 0 );
167+ }
168+ return false ;
169+ }
157170}
0 commit comments