From a0fa4b7347ea52c699bc589a0fd5572df56c140f Mon Sep 17 00:00:00 2001 From: peterjurkovic Date: Tue, 14 Nov 2017 11:40:02 +0000 Subject: [PATCH 1/2] Fix ClassNameIdResolver - support for Set and Map collections --- .../jsontype/impl/ClassNameIdResolver.java | 27 ++++--- .../impl/ClassNameIdResolverTest.java | 74 +++++++++++++++++++ 2 files changed, 91 insertions(+), 10 deletions(-) create mode 100644 src/test/java/com/fasterxml/jackson/databind/jsontype/impl/ClassNameIdResolverTest.java diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/ClassNameIdResolver.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/ClassNameIdResolver.java index d93b8cada3..1cb8ae276e 100644 --- a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/ClassNameIdResolver.java +++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/ClassNameIdResolver.java @@ -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)) { @@ -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) { @@ -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; + } } diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/impl/ClassNameIdResolverTest.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/impl/ClassNameIdResolverTest.java new file mode 100644 index 0000000000..3c84031a99 --- /dev/null +++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/impl/ClassNameIdResolverTest.java @@ -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 utilMap = Collections.singletonMap("ANY_KEY", "ANY_VALUE"); + + String clazz = classNameIdResolver.idFromValue( utilMap ); + + assertEquals(clazz, "java.util.HashMap"); + } + + @Test + public void testIdFromValue_shouldUseJavaUtilHashSetForSingletonSet(){ + Set utilSet = Collections.singleton("ANY_VALUE"); + + String clazz = classNameIdResolver.idFromValue( utilSet ); + + assertEquals(clazz, "java.util.HashSet"); + } + + @Test + public void testIdFromValue_shouldUseJavaUtilArrayListSetForSingletonSet(){ + List utilList = Collections.singletonList("ANY_VALUE"); + + String clazz = classNameIdResolver.idFromValue( utilList ); + + assertEquals(clazz, "java.util.ArrayList"); + } + + @Test + public void testIdFromValue_shouldUseJavaUtilArrayListSetForArraysList(){ + List utilList = Arrays.asList("ANY_VALUE"); + + String clazz = classNameIdResolver.idFromValue( utilList ); + + assertEquals(clazz, "java.util.ArrayList"); + } +} From bd9457ee2de74293af904f40f34a38a93b9a14d3 Mon Sep 17 00:00:00 2001 From: peterjurkovic Date: Tue, 14 Nov 2017 11:48:14 +0000 Subject: [PATCH 2/2] Typo fix in tests --- .../jsontype/impl/ClassNameIdResolverTest.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/impl/ClassNameIdResolverTest.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/impl/ClassNameIdResolverTest.java index 3c84031a99..5da854d4b6 100644 --- a/src/test/java/com/fasterxml/jackson/databind/jsontype/impl/ClassNameIdResolverTest.java +++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/impl/ClassNameIdResolverTest.java @@ -38,33 +38,33 @@ public void setup(){ @Test public void testIdFromValue_shouldUseJavaUtilHashMapForSingletonMap(){ - Map utilMap = Collections.singletonMap("ANY_KEY", "ANY_VALUE"); + Map singletonMap = Collections.singletonMap("ANY_KEY", "ANY_VALUE"); - String clazz = classNameIdResolver.idFromValue( utilMap ); + String clazz = classNameIdResolver.idFromValue( singletonMap ); assertEquals(clazz, "java.util.HashMap"); } @Test public void testIdFromValue_shouldUseJavaUtilHashSetForSingletonSet(){ - Set utilSet = Collections.singleton("ANY_VALUE"); + Set singletonSet = Collections.singleton("ANY_VALUE"); - String clazz = classNameIdResolver.idFromValue( utilSet ); + String clazz = classNameIdResolver.idFromValue( singletonSet ); assertEquals(clazz, "java.util.HashSet"); } @Test - public void testIdFromValue_shouldUseJavaUtilArrayListSetForSingletonSet(){ - List utilList = Collections.singletonList("ANY_VALUE"); + public void testIdFromValue_shouldUseJavaUtilArrayListForSingletonList(){ + List singletonList = Collections.singletonList("ANY_VALUE"); - String clazz = classNameIdResolver.idFromValue( utilList ); + String clazz = classNameIdResolver.idFromValue( singletonList ); assertEquals(clazz, "java.util.ArrayList"); } @Test - public void testIdFromValue_shouldUseJavaUtilArrayListSetForArraysList(){ + public void testIdFromValue_shouldUseJavaUtilArrayListForArrays$List(){ List utilList = Arrays.asList("ANY_VALUE"); String clazz = classNameIdResolver.idFromValue( utilList );