Skip to content

Commit a4f093f

Browse files
committed
Fixing #406
1 parent 342bebe commit a4f093f

File tree

3 files changed

+58
-28
lines changed

3 files changed

+58
-28
lines changed

src/main/java/com/fasterxml/jackson/databind/annotation/JsonTypeIdResolver.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,11 @@
1818
* for converting between java types and type id included in JSON content.
1919
* In simplest cases this can be a simple class with static mapping between
2020
* type names and matching classes.
21+
*<p>
22+
* NOTE: since 2.4, applicable to properties as well (should have been long time
23+
* ago, but problem only found then)
2124
*/
22-
@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE})
25+
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.TYPE, ElementType.PARAMETER})
2326
@Retention(RetentionPolicy.RUNTIME)
2427
@JacksonAnnotation
2528
public @interface JsonTypeIdResolver

src/main/java/com/fasterxml/jackson/databind/annotation/JsonTypeResolver.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,11 @@
99
* used for handling serialization and deserialization of type information,
1010
* needed for handling of polymorphic types (or sometimes just for linking
1111
* abstract types to concrete types)
12+
*<p>
13+
* NOTE: since 2.4, applicable to properties as well (should have been long time
14+
* ago, but problem only found then)
1215
*/
13-
@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE})
16+
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.TYPE, ElementType.PARAMETER})
1417
@Retention(RetentionPolicy.RUNTIME)
1518
@com.fasterxml.jackson.annotation.JacksonAnnotation
1619
public @interface JsonTypeResolver

src/test/java/com/fasterxml/jackson/databind/jsontype/TestCustomTypeIdResolver.java

+50-26
Original file line numberDiff line numberDiff line change
@@ -26,27 +26,57 @@ public CustomBeanImpl() { }
2626
public CustomBeanImpl(int x) { this.x = x; }
2727
}
2828

29-
static class CustomBeanWrapper {
30-
// @JsonTypeInfo(use=Id.NONE, include=As.EXTERNAL_PROPERTY, property="type")
31-
@JsonTypeInfo(use=Id.CUSTOM, include=As.PROPERTY, property="type")
32-
public CustomBean value;
29+
static class ExtBeanWrapper {
30+
@JsonTypeInfo(use=Id.CUSTOM, include=As.EXTERNAL_PROPERTY, property="type")
31+
@JsonTypeIdResolver(ExtResolver.class)
32+
public ExtBean value;
3333
}
34-
35-
static class CustomResolver implements TypeIdResolver
36-
{
34+
35+
static class CustomResolver extends CustomResolverBase {
36+
// yes, static: just for test purposes, not real use
3737
static List<JavaType> initTypes;
3838

39-
public CustomResolver() { }
39+
public CustomResolver() {
40+
super(CustomBean.class, CustomBeanImpl.class);
41+
}
4042

4143
@Override
42-
public Id getMechanism() {
43-
return Id.CUSTOM;
44+
public void init(JavaType baseType) {
45+
if (initTypes != null) {
46+
initTypes.add(baseType);
47+
}
4448
}
49+
}
50+
51+
static abstract class ExtBean { }
4552

46-
@Override
47-
public String idFromValue(Object value)
48-
{
49-
if (value instanceof CustomBean) {
53+
static class ExtBeanImpl extends ExtBean {
54+
public int y;
55+
56+
public ExtBeanImpl() { }
57+
public ExtBeanImpl(int y) { this.y = y; }
58+
}
59+
60+
static class ExtResolver extends CustomResolverBase {
61+
public ExtResolver() {
62+
super(ExtBean.class, ExtBeanImpl.class);
63+
}
64+
}
65+
66+
static class CustomResolverBase implements TypeIdResolver
67+
{
68+
protected final Class<?> superType;
69+
protected final Class<?> subType;
70+
71+
public CustomResolverBase(Class<?> baseType, Class<?> implType) {
72+
superType = baseType;
73+
subType = implType;
74+
}
75+
76+
@Override public Id getMechanism() { return Id.CUSTOM; }
77+
78+
@Override public String idFromValue(Object value) {
79+
if (superType.isAssignableFrom(value.getClass())) {
5080
return "*";
5181
}
5282
return "unknown";
@@ -58,17 +88,13 @@ public String idFromValueAndType(Object value, Class<?> type) {
5888
}
5989

6090
@Override
61-
public void init(JavaType baseType) {
62-
if (initTypes != null) {
63-
initTypes.add(baseType);
64-
}
65-
}
91+
public void init(JavaType baseType) { }
6692

6793
@Override
6894
public JavaType typeFromId(String id)
6995
{
7096
if ("*".equals(id)) {
71-
return TypeFactory.defaultInstance().constructType(CustomBeanImpl.class);
97+
return TypeFactory.defaultInstance().constructType(subType);
7298
}
7399
return null;
74100
}
@@ -109,16 +135,14 @@ public void testCustomTypeIdResolver() throws Exception
109135

110136
public void testCustomWithExternal() throws Exception
111137
{
112-
CustomBeanWrapper w = new CustomBeanWrapper();
113-
w.value = new CustomBeanImpl(12);
138+
ExtBeanWrapper w = new ExtBeanWrapper();
139+
w.value = new ExtBeanImpl(12);
114140

115141
String json = MAPPER.writeValueAsString(w);
116142

117-
System.out.println("JSON = "+json);
118-
119-
CustomBeanWrapper out = MAPPER.readValue(json, CustomBeanWrapper.class);
143+
ExtBeanWrapper out = MAPPER.readValue(json, ExtBeanWrapper.class);
120144
assertNotNull(out);
121145

122-
assertEquals(12, ((CustomBeanImpl) out.value).x);
146+
assertEquals(12, ((ExtBeanImpl) out.value).y);
123147
}
124148
}

0 commit comments

Comments
 (0)