Fixing #406
diff --git a/src/main/java/com/fasterxml/jackson/databind/annotation/JsonTypeIdResolver.java b/src/main/java/com/fasterxml/jackson/databind/annotation/JsonTypeIdResolver.java
index c8d0f4f..8aa41cb 100644
--- a/src/main/java/com/fasterxml/jackson/databind/annotation/JsonTypeIdResolver.java
+++ b/src/main/java/com/fasterxml/jackson/databind/annotation/JsonTypeIdResolver.java
@@ -18,8 +18,11 @@
* for converting between java types and type id included in JSON content.
* In simplest cases this can be a simple class with static mapping between
* type names and matching classes.
+ *<p>
+ * NOTE: since 2.4, applicable to properties as well (should have been long time
+ * ago, but problem only found then)
*/
-@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE})
+@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.TYPE, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JsonTypeIdResolver
diff --git a/src/main/java/com/fasterxml/jackson/databind/annotation/JsonTypeResolver.java b/src/main/java/com/fasterxml/jackson/databind/annotation/JsonTypeResolver.java
index 53156d2..b46e0aa 100644
--- a/src/main/java/com/fasterxml/jackson/databind/annotation/JsonTypeResolver.java
+++ b/src/main/java/com/fasterxml/jackson/databind/annotation/JsonTypeResolver.java
@@ -9,8 +9,11 @@
* used for handling serialization and deserialization of type information,
* needed for handling of polymorphic types (or sometimes just for linking
* abstract types to concrete types)
+ *<p>
+ * NOTE: since 2.4, applicable to properties as well (should have been long time
+ * ago, but problem only found then)
*/
-@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE})
+@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.TYPE, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@com.fasterxml.jackson.annotation.JacksonAnnotation
public @interface JsonTypeResolver
diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestCustomTypeIdResolver.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestCustomTypeIdResolver.java
index 4fb6fde..98b3d91 100644
--- a/src/test/java/com/fasterxml/jackson/databind/jsontype/TestCustomTypeIdResolver.java
+++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/TestCustomTypeIdResolver.java
@@ -26,27 +26,57 @@
public CustomBeanImpl(int x) { this.x = x; }
}
- static class CustomBeanWrapper {
-// @JsonTypeInfo(use=Id.NONE, include=As.EXTERNAL_PROPERTY, property="type")
- @JsonTypeInfo(use=Id.CUSTOM, include=As.PROPERTY, property="type")
- public CustomBean value;
+ static class ExtBeanWrapper {
+ @JsonTypeInfo(use=Id.CUSTOM, include=As.EXTERNAL_PROPERTY, property="type")
+ @JsonTypeIdResolver(ExtResolver.class)
+ public ExtBean value;
}
-
- static class CustomResolver implements TypeIdResolver
- {
+
+ static class CustomResolver extends CustomResolverBase {
+ // yes, static: just for test purposes, not real use
static List<JavaType> initTypes;
- public CustomResolver() { }
-
- @Override
- public Id getMechanism() {
- return Id.CUSTOM;
+ public CustomResolver() {
+ super(CustomBean.class, CustomBeanImpl.class);
}
@Override
- public String idFromValue(Object value)
- {
- if (value instanceof CustomBean) {
+ public void init(JavaType baseType) {
+ if (initTypes != null) {
+ initTypes.add(baseType);
+ }
+ }
+ }
+
+ static abstract class ExtBean { }
+
+ static class ExtBeanImpl extends ExtBean {
+ public int y;
+
+ public ExtBeanImpl() { }
+ public ExtBeanImpl(int y) { this.y = y; }
+ }
+
+ static class ExtResolver extends CustomResolverBase {
+ public ExtResolver() {
+ super(ExtBean.class, ExtBeanImpl.class);
+ }
+ }
+
+ static class CustomResolverBase implements TypeIdResolver
+ {
+ protected final Class<?> superType;
+ protected final Class<?> subType;
+
+ public CustomResolverBase(Class<?> baseType, Class<?> implType) {
+ superType = baseType;
+ subType = implType;
+ }
+
+ @Override public Id getMechanism() { return Id.CUSTOM; }
+
+ @Override public String idFromValue(Object value) {
+ if (superType.isAssignableFrom(value.getClass())) {
return "*";
}
return "unknown";
@@ -58,17 +88,13 @@
}
@Override
- public void init(JavaType baseType) {
- if (initTypes != null) {
- initTypes.add(baseType);
- }
- }
+ public void init(JavaType baseType) { }
@Override
public JavaType typeFromId(String id)
{
if ("*".equals(id)) {
- return TypeFactory.defaultInstance().constructType(CustomBeanImpl.class);
+ return TypeFactory.defaultInstance().constructType(subType);
}
return null;
}
@@ -109,16 +135,14 @@
public void testCustomWithExternal() throws Exception
{
- CustomBeanWrapper w = new CustomBeanWrapper();
- w.value = new CustomBeanImpl(12);
+ ExtBeanWrapper w = new ExtBeanWrapper();
+ w.value = new ExtBeanImpl(12);
String json = MAPPER.writeValueAsString(w);
-System.out.println("JSON = "+json);
-
- CustomBeanWrapper out = MAPPER.readValue(json, CustomBeanWrapper.class);
+ ExtBeanWrapper out = MAPPER.readValue(json, ExtBeanWrapper.class);
assertNotNull(out);
- assertEquals(12, ((CustomBeanImpl) out.value).x);
+ assertEquals(12, ((ExtBeanImpl) out.value).y);
}
}