Skip to content

Commit

Permalink
Use key type factory methods ahead of ctors
Browse files Browse the repository at this point in the history
Fixes #2158

Simply swaps the order factory method and String
constructors are searched for in the key type.
Factory methods are now preferred.
  • Loading branch information
tbartley committed Jul 5, 2019
1 parent e370d32 commit 07aca04
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,7 @@ public static KeyDeserializer findStringBasedKeyDeserializer(DeserializationCont
// We don't need full deserialization information, just need to know creators.
BeanDescription beanDesc = ctxt.introspect(type);

// Ok, so: can we find T(String) constructor?
Constructor<?> ctor = beanDesc.findSingleArgConstructor(String.class);
if (ctor != null) {
if (ctxt.canOverrideAccessModifiers()) {
ClassUtil.checkAndFixAccess(ctor, ctxt.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));
}
return new StdKeyDeserializer.StringCtorKeyDeserializer(ctor);
}
/* or if not, "static T valueOf(String)" (or equivalent marked
/* Ok, so: can we find "static T valueOf(String)" (or equivalent marked
* with @JsonCreator annotation?)
*/
Method m = beanDesc.findFactoryMethod(String.class);
Expand All @@ -70,6 +62,16 @@ public static KeyDeserializer findStringBasedKeyDeserializer(DeserializationCont
}
return new StdKeyDeserializer.StringFactoryKeyDeserializer(m);
}

// or if not, a T(String) constructor?
Constructor<?> ctor = beanDesc.findSingleArgConstructor(String.class);
if (ctor != null) {
if (ctxt.canOverrideAccessModifiers()) {
ClassUtil.checkAndFixAccess(ctor, ctxt.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));
}
return new StdKeyDeserializer.StringCtorKeyDeserializer(ctor);
}

// nope, no such luck...
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,28 @@ public static KeyTypeFactory create(String str) {
return new KeyTypeFactory(str, true);
}
}


static class KeyTypeFactoryPrecedence {
protected String value;
public KeyTypeFactoryPrecedence(String v) {
this(v, false);
}

private KeyTypeFactoryPrecedence(String v, boolean factory) {
if (factory) {
value = "factory:" + v;
}
else {
value = "ctor:" + v;
}
}

@JsonCreator
public static KeyTypeFactoryPrecedence create(String str) {
return new KeyTypeFactoryPrecedence(str, true);
}
}

/*
/**********************************************************
/* Test methods for sub-classing
Expand Down Expand Up @@ -167,4 +188,18 @@ public void testKeyViaFactory() throws Exception
assertEquals("a", ((KeyTypeFactory) key).value);
}


public void testKeyViaFactoryPrecedenceOverConstructor() throws Exception
{
ObjectMapper mapper = new ObjectMapper();
Map<KeyTypeFactoryPrecedence,Integer> map = mapper.readValue("{\"a\":123}",
TypeFactory.defaultInstance().constructMapType(HashMap.class, KeyTypeFactoryPrecedence.class, Integer.class));
assertEquals(1, map.size());
Map.Entry<?,?> entry = map.entrySet().iterator().next();
assertEquals(Integer.valueOf(123), entry.getValue());
Object key = entry.getKey();
assertEquals(KeyTypeFactoryPrecedence.class, key.getClass());
assertEquals("factory:a", ((KeyTypeFactoryPrecedence) key).value);
}

}

0 comments on commit 07aca04

Please sign in to comment.