Skip to content

Commit 12f82c6

Browse files
committed
Fix #1328
1 parent bf261d4 commit 12f82c6

File tree

4 files changed

+104
-5
lines changed

4 files changed

+104
-5
lines changed

release-notes/VERSION-2.x

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Project: jackson-databind
99
#955: Add `MapperFeature.USE_BASE_TYPE_AS_DEFAULT_IMPL` to use declared base type
1010
as `defaultImpl` for polymorphic deserialization
1111
(contributed by mikeldpl@github)
12+
#1328: External property polymorphic deserialization does not work with enums
1213
#1565: Deserialization failure with Polymorphism using JsonTypeInfo `defaultImpl`,
1314
subtype as target
1415
#1964: Failed to specialize `Map` type during serialization where key type

src/main/java/com/fasterxml/jackson/databind/deser/impl/ExternalTypeHandler.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,6 @@ public Object complete(JsonParser p, DeserializationContext ctxt,
262262
for (int i = 0; i < len; ++i) {
263263
String typeId = _typeIds[i];
264264
final ExtTypedProperty extProp = _properties[i];
265-
266265
if (typeId == null) {
267266
// let's allow missing both type and property (may already have been set, too)
268267
if (_tokens[i] == null) {
@@ -294,11 +293,21 @@ public Object complete(JsonParser p, DeserializationContext ctxt,
294293
SettableBeanProperty typeProp = extProp.getTypeProperty();
295294
// for now, should only be needed for creator properties, too
296295
if ((typeProp != null) && (typeProp.getCreatorIndex() >= 0)) {
297-
buffer.assignParameter(typeProp, typeId);
296+
// 31-May-2018, tatu: [databind#1328] if id is NOT plain `String`, need to
297+
// apply deserializer... fun fun.
298+
final Object v;
299+
if (typeProp.getType().hasRawClass(String.class)) {
300+
v = typeId;
301+
} else {
302+
TokenBuffer tb = new TokenBuffer(p, ctxt);
303+
tb.writeString(typeId);
304+
v = typeProp.getValueDeserializer().deserialize(tb.asParserOnFirstToken(), ctxt);
305+
tb.close();
306+
}
307+
buffer.assignParameter(typeProp, v);
298308
}
299309
}
300310
}
301-
302311
Object bean = creator.build(ctxt, buffer);
303312
// third: assign non-creator properties
304313
for (int i = 0; i < len; ++i) {

src/main/java/com/fasterxml/jackson/databind/deser/impl/PropertyValueBuffer.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,6 @@ public Object[] getParameters(SettableBeanProperty[] props)
177177
}
178178
}
179179
}
180-
181180
return _creatorParameters;
182181
}
183182

@@ -263,7 +262,6 @@ public boolean assignParameter(SettableBeanProperty prop, Object value)
263262
{
264263
final int ix = prop.getCreatorIndex();
265264
_creatorParameters[ix] = value;
266-
267265
if (_paramsSeenBig == null) {
268266
int old = _paramsSeen;
269267
int newValue = (old | (1 << ix));
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package com.fasterxml.jackson.databind.jsontype.ext;
2+
3+
import java.io.IOException;
4+
import java.util.Arrays;
5+
import java.util.List;
6+
7+
import com.fasterxml.jackson.annotation.JsonTypeInfo;
8+
import com.fasterxml.jackson.core.type.TypeReference;
9+
import com.fasterxml.jackson.databind.*;
10+
import com.fasterxml.jackson.databind.annotation.JsonTypeIdResolver;
11+
import com.fasterxml.jackson.databind.jsontype.TypeIdResolver;
12+
13+
public class ExternalTypeIdWithEnum1328Test extends BaseMapTest
14+
{
15+
public interface Animal { }
16+
17+
public static class Dog implements Animal {
18+
public String dogStuff;
19+
}
20+
21+
public enum AnimalType {
22+
Dog;
23+
}
24+
25+
public static class AnimalAndType {
26+
public AnimalType type;
27+
28+
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS,
29+
include = JsonTypeInfo.As.EXTERNAL_PROPERTY,
30+
property = "type")
31+
@JsonTypeIdResolver(AnimalResolver.class)
32+
private Animal animal;
33+
34+
public AnimalAndType() { }
35+
36+
// problem is this annotation
37+
@java.beans.ConstructorProperties({"type", "animal"})
38+
public AnimalAndType(final AnimalType type, final Animal animal) {
39+
this.type = type;
40+
this.animal = animal;
41+
}
42+
}
43+
44+
static class AnimalResolver implements TypeIdResolver {
45+
@Override
46+
public void init(JavaType bt) { }
47+
48+
@Override
49+
public String idFromValue(Object value) {
50+
return null;
51+
}
52+
53+
@Override
54+
public String idFromValueAndType(Object value, Class<?> suggestedType) {
55+
return null;
56+
}
57+
58+
@Override
59+
public String idFromBaseType() {
60+
throw new UnsupportedOperationException("Missing action type information - Can not construct");
61+
}
62+
63+
@Override
64+
public JavaType typeFromId(DatabindContext context, String id) throws IOException {
65+
if (AnimalType.Dog.toString().equals(id)) {
66+
return context.constructType(Dog.class);
67+
}
68+
throw new IllegalArgumentException("What is a " + id);
69+
}
70+
71+
@Override
72+
public String getDescForKnownTypeIds() {
73+
return null;
74+
}
75+
76+
@Override
77+
public JsonTypeInfo.Id getMechanism() {
78+
return JsonTypeInfo.Id.CUSTOM;
79+
}
80+
}
81+
82+
public void testExample() throws Exception {
83+
ObjectMapper mapper = new ObjectMapper();
84+
85+
String json = mapper.writerWithDefaultPrettyPrinter()
86+
.writeValueAsString(Arrays.asList(new AnimalAndType(AnimalType.Dog, new Dog())));
87+
List<AnimalAndType> list = mapper.readerFor(new TypeReference<List<AnimalAndType>>() { })
88+
.readValue(json);
89+
assertNotNull(list);
90+
}
91+
}

0 commit comments

Comments
 (0)