Skip to content

Commit

Permalink
ClassNameIdResolver doesn't handle resolve Collections$SingletonMap &…
Browse files Browse the repository at this point in the history
… Collections$SingletonSet (#1823)

Fix ClassNameIdResolver - support for Set and Map collections
  • Loading branch information
peterjurkovic authored and cowtowncoder committed Dec 4, 2017
1 parent fb2d03c commit 8d6c35d
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ protected JavaType _typeFromId(String id, DatabindContext ctxt) throws IOExcepti
/**********************************************************
*/

protected final String _idFrom(Object value, Class<?> cls, TypeFactory typeFactory)
protected String _idFrom(Object value, Class<?> cls, TypeFactory typeFactory)
{
// Need to ensure that "enum subtypes" work too
if (Enum.class.isAssignableFrom(cls)) {
Expand All @@ -87,16 +87,18 @@ protected final String _idFrom(Object value, Class<?> cls, TypeFactory typeFacto
// not optimal: but EnumMap is not a customizable type so this is sort of ok
str = typeFactory.constructMapType(EnumMap.class, enumClass, valueClass).toCanonical();
} else {
String end = str.substring(9);
if ((end.startsWith(".Arrays$") || end.startsWith(".Collections$"))
&& str.indexOf("List") >= 0) {
/* 17-Feb-2010, tatus: Another such case: result of
* Arrays.asList() is named like so in Sun JDK...
* Let's just plain old ArrayList in its place
* NOTE: chances are there are plenty of similar cases
* for other wrappers... (immutable, singleton, synced etc)
*/
/* 17-Feb-2010, tatus: Another such case: result of
* Arrays.asList() is named like so in Sun JDK...
* Let's just plain old ArrayList in its place
* NOTE: chances are there are plenty of similar cases
* for other wrappers... (immutable, singleton, synced etc)
*/
if (isJavaUtilCollectionClass(str, "List")) {
str = "java.util.ArrayList";
}else if(isJavaUtilCollectionClass(str, "Map")){
str = "java.util.HashMap";
}else if(isJavaUtilCollectionClass(str, "Set")){
str = "java.util.HashSet";
}
}
} else if (str.indexOf('$') >= 0) {
Expand Down Expand Up @@ -128,4 +130,9 @@ protected final String _idFrom(Object value, Class<?> cls, TypeFactory typeFacto
public String getDescForKnownTypeIds() {
return "class name used as type id";
}

private static boolean isJavaUtilCollectionClass(String clazzName, String type){
String end = clazzName.substring(9);
return (end.startsWith(".Collections$") || end.startsWith(".Arrays$")) && clazzName.indexOf(type) > 0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package com.fasterxml.jackson.databind.jsontype.impl;

import static org.junit.Assert.assertEquals;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import com.fasterxml.jackson.databind.type.TypeFactory;

import com.fasterxml.jackson.databind.JavaType;

@RunWith(PowerMockRunner.class)
@PrepareForTest(TypeFactory.class)
public class ClassNameIdResolverTest {

@Mock
private JavaType javaType;

@Mock
private TypeFactory typeFactory;


private ClassNameIdResolver classNameIdResolver;

@Before
public void setup(){
this.classNameIdResolver = new ClassNameIdResolver(javaType, typeFactory);
}

@Test
public void testIdFromValue_shouldUseJavaUtilHashMapForSingletonMap(){
Map<String, String> singletonMap = Collections.singletonMap("ANY_KEY", "ANY_VALUE");

String clazz = classNameIdResolver.idFromValue( singletonMap );

assertEquals(clazz, "java.util.HashMap");
}

@Test
public void testIdFromValue_shouldUseJavaUtilHashSetForSingletonSet(){
Set<String> singletonSet = Collections.singleton("ANY_VALUE");

String clazz = classNameIdResolver.idFromValue( singletonSet );

assertEquals(clazz, "java.util.HashSet");
}

@Test
public void testIdFromValue_shouldUseJavaUtilArrayListForSingletonList(){
List<String> singletonList = Collections.singletonList("ANY_VALUE");

String clazz = classNameIdResolver.idFromValue( singletonList );

assertEquals(clazz, "java.util.ArrayList");
}

@Test
public void testIdFromValue_shouldUseJavaUtilArrayListForArrays$List(){
List<String> utilList = Arrays.asList("ANY_VALUE");

String clazz = classNameIdResolver.idFromValue( utilList );

assertEquals(clazz, "java.util.ArrayList");
}
}

0 comments on commit 8d6c35d

Please sign in to comment.