Skip to content

Commit 2e2f4e1

Browse files
committed
Fixed #955 (or rather, added release notes, refactored earlier merge)
1 parent 98068c7 commit 2e2f4e1

File tree

8 files changed

+110
-62
lines changed

8 files changed

+110
-62
lines changed

release-notes/VERSION-2.x

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@ Project: jackson-databind
66

77
2.9.6 (not yet released)
88

9+
#955: Add `MapperFeature.USE_BASE_TYPE_AS_DEFAULT_IMPL` to use declared base type
10+
as `defaultImpl` for polymorphic deserialization
11+
(contributed by mikeldpl@github)
912
#1565: Deserialization failure with Polymorphism using JsonTypeInfo `defaultImpl`,
1013
subtype as target
1114
#1964: Failed to specialize `Map` type during serialization where key type

src/main/java/com/fasterxml/jackson/databind/DeserializationFeature.java

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -459,14 +459,6 @@ public enum DeserializationFeature implements ConfigFeature
459459
*/
460460
ADJUST_DATES_TO_CONTEXT_TIME_ZONE(true),
461461

462-
/**
463-
* Feature that specifies whether the given concrete class is used
464-
* if type property is missing.
465-
*
466-
* @since 2.9
467-
*/
468-
USE_BASE_TYPE_AS_DEFAULT(false),
469-
470462
/*
471463
/******************************************************
472464
/* Other

src/main/java/com/fasterxml/jackson/databind/MapperFeature.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,20 @@ public enum MapperFeature implements ConfigFeature
286286
*/
287287
USE_STATIC_TYPING(false),
288288

289+
/**
290+
* Feature that specifies whether the declared base type of a polymorphic value
291+
* is to be used as the "default" implementation, if no explicit default class
292+
* is specified via {@code @JsonTypeInfo.defaultImpl} annotation.
293+
*<p>
294+
* Note that feature only has effect on deserialization of regular polymorphic properties:
295+
* it does NOT affect non-polymorphic cases, and is unlikely to work with Default Typing.
296+
*<p>
297+
* Feature is disabled by default for backwards compatibility.
298+
*
299+
* @since 2.9.6
300+
*/
301+
USE_BASE_TYPE_AS_DEFAULT_IMPL(false),
302+
289303
/*
290304
/******************************************************
291305
/* View-related features

src/main/java/com/fasterxml/jackson/databind/jsontype/impl/StdTypeResolverBuilder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ protected JavaType defineDefaultImpl(DeserializationConfig config, JavaType base
145145
JavaType defaultImpl;
146146
if (_defaultImpl == null) {
147147
//Fis of issue #955
148-
if (config.isEnabled(DeserializationFeature.USE_BASE_TYPE_AS_DEFAULT) && !baseType.isAbstract()) {
148+
if (config.isEnabled(MapperFeature.USE_BASE_TYPE_AS_DEFAULT_IMPL) && !baseType.isAbstract()) {
149149
defaultImpl = baseType;
150150
} else {
151151
defaultImpl = null;

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,14 +88,13 @@ final static class BeanWithAnon {
8888
public String toString() { return "sub!"; }
8989
};
9090
}
91-
91+
9292
/*
9393
/**********************************************************
94-
/* Unit tests
94+
/* Test methods
9595
/**********************************************************
9696
*/
9797

98-
// Testing [JACKSON-498], partial fix
9998
public void testEmptyCollection() throws Exception
10099
{
101100
ObjectMapper mapper = new ObjectMapper();
Lines changed: 45 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,91 @@
11
package com.fasterxml.jackson.databind.jsontype;
22

33
import com.fasterxml.jackson.annotation.JsonTypeInfo;
4+
45
import com.fasterxml.jackson.databind.BaseMapTest;
5-
import com.fasterxml.jackson.databind.DeserializationFeature;
66
import com.fasterxml.jackson.databind.JsonMappingException;
7+
import com.fasterxml.jackson.databind.MapperFeature;
78
import com.fasterxml.jackson.databind.ObjectMapper;
89

910
import java.io.IOException;
1011

11-
public class TestBaseTypeAsDefault extends BaseMapTest {
12+
public class TestBaseTypeAsDefault extends BaseMapTest
13+
{
14+
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "@class")
15+
static class Parent {
16+
}
1217

13-
private ObjectMapper objectMapper;
1418

15-
@Override
16-
public void setUp() {
17-
objectMapper = new ObjectMapper();
18-
objectMapper.enable(DeserializationFeature.USE_BASE_TYPE_AS_DEFAULT);
19+
static class Child extends Parent {
1920
}
2021

21-
public void testPositiveForParent() throws IOException {
22-
Object o = objectMapper.readerFor(Parent.class).readValue("{}");
2322

23+
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "@class", defaultImpl = ChildOfChild.class)
24+
static abstract class AbstractParentWithDefault {
25+
}
26+
27+
28+
static class ChildOfAbstract extends AbstractParentWithDefault {
29+
}
30+
31+
static class ChildOfChild extends ChildOfAbstract {
32+
}
33+
34+
/*
35+
/**********************************************************
36+
/* Test methods
37+
/**********************************************************
38+
*/
39+
40+
protected ObjectMapper MAPPER_WITH_BASE = new ObjectMapper()
41+
.enable(MapperFeature.USE_BASE_TYPE_AS_DEFAULT_IMPL);
42+
43+
protected ObjectMapper MAPPER_WITHOUT_BASE = new ObjectMapper()
44+
.disable(MapperFeature.USE_BASE_TYPE_AS_DEFAULT_IMPL);
45+
46+
public void testPositiveForParent() throws IOException {
47+
Object o = MAPPER_WITH_BASE.readerFor(Parent.class).readValue("{}");
2448
assertEquals(o.getClass(), Parent.class);
2549
}
2650

2751
public void testPositiveForChild() throws IOException {
28-
Object o = objectMapper.readerFor(Child.class).readValue("{}");
29-
52+
Object o = MAPPER_WITH_BASE.readerFor(Child.class).readValue("{}");
3053
assertEquals(o.getClass(), Child.class);
3154
}
3255

3356
public void testNegativeForParent() throws IOException {
34-
objectMapper.disable(DeserializationFeature.USE_BASE_TYPE_AS_DEFAULT);
35-
3657
try {
37-
Object o = objectMapper.readerFor(Parent.class).readValue("{}");
58+
/*Object o =*/ MAPPER_WITHOUT_BASE.readerFor(Parent.class).readValue("{}");
59+
fail("Should not pass");
3860
} catch (JsonMappingException ex) {
3961
assertTrue(ex.getMessage().contains("missing type id property '@class'"));
4062
}
4163
}
4264

4365
public void testNegativeForChild() throws IOException {
44-
objectMapper.disable(DeserializationFeature.USE_BASE_TYPE_AS_DEFAULT);
45-
4666
try {
47-
Object o = objectMapper.readerFor(Child.class).readValue("{}");
67+
/*Object o =*/ MAPPER_WITHOUT_BASE.readerFor(Child.class).readValue("{}");
68+
fail("Should not pass");
4869
} catch (JsonMappingException ex) {
4970
assertTrue(ex.getMessage().contains("missing type id property '@class'"));
5071
}
5172
}
5273

53-
public void testNegativeConversionForAbstract() throws IOException {
54-
try {
55-
Object o = objectMapper.readerFor(AbstractParentWithDefault.class).readValue("{}");
56-
} catch (JsonMappingException ex) {
57-
assertTrue(ex.getMessage().contains("missing property '@class'"));
58-
}
74+
public void testConversionForAbstractWithDefault() throws IOException {
75+
// should pass shouldn't it?
76+
Object o = MAPPER_WITH_BASE.readerFor(AbstractParentWithDefault.class).readValue("{}");
77+
assertEquals(o.getClass(), ChildOfChild.class);
5978
}
6079

6180
public void testPositiveWithTypeSpecification() throws IOException {
62-
Object o = objectMapper.readerFor(Parent.class)
63-
.readValue("{\"@class\":\"com.fasterxml.jackson.databind.jsontype.TestBaseTypeAsDefault$Child\"}");
64-
81+
Object o = MAPPER_WITH_BASE.readerFor(Parent.class)
82+
.readValue("{\"@class\":\""+Child.class.getName()+"\"}");
6583
assertEquals(o.getClass(), Child.class);
6684
}
6785

6886
public void testPositiveWithManualDefault() throws IOException {
69-
Object o = objectMapper.readerFor(ChildOfAbstract.class).readValue("{}");
87+
Object o = MAPPER_WITH_BASE.readerFor(ChildOfAbstract.class).readValue("{}");
7088

7189
assertEquals(o.getClass(), ChildOfChild.class);
7290
}
73-
74-
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "@class")
75-
static class Parent {
76-
}
77-
78-
79-
static class Child extends Parent {
80-
}
81-
82-
83-
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "@class", defaultImpl = ChildOfChild.class)
84-
static abstract class AbstractParentWithDefault {
85-
}
86-
87-
88-
static class ChildOfAbstract extends AbstractParentWithDefault {
89-
}
90-
91-
static class ChildOfChild extends ChildOfAbstract {
92-
}
9391
}

src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinDeserForCreators.java

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ static class StringWrapper {
6868
private StringWrapper(String s, boolean foo) { _value = s; }
6969

7070
@SuppressWarnings("unused")
71-
private static StringWrapper create(String str) {
71+
private static StringWrapper create(String str) {
7272
return new StringWrapper(str, false);
7373
}
7474
}
@@ -77,6 +77,34 @@ abstract static class StringWrapperMixIn {
7777
@JsonCreator static StringWrapper create(String str) { return null; }
7878
}
7979

80+
// [databind#2020]
81+
@JsonIgnoreProperties("size")
82+
abstract class MyPairMixIn8 { // with and without <Long, String>
83+
@JsonCreator
84+
public Pair2020 with(@JsonProperty("value0") Object value0,
85+
@JsonProperty("value1") Object value1)
86+
{
87+
// body does not matter, only signature
88+
return null;
89+
}
90+
}
91+
92+
static class Pair2020 {
93+
final int x, y;
94+
95+
private Pair2020(int x0, int y0) {
96+
x = x0;
97+
y = y0;
98+
}
99+
100+
@JsonCreator
101+
static Pair2020 with(Object x0, Object y0) {
102+
// static Pair2020 with(@JsonProperty("value0") Object x0, @JsonProperty("value1")Object y0) {
103+
return new Pair2020(((Number) x0).intValue(),
104+
((Number) y0).intValue());
105+
}
106+
}
107+
80108
/*
81109
/**********************************************************
82110
/* Unit tests
@@ -107,11 +135,25 @@ public void testForFactoryAndCtor() throws IOException
107135
assertEquals("stringX", result._a);
108136
}
109137

110-
public void testFactoryMixIn() throws IOException
138+
public void testFactoryDelegateMixIn() throws IOException
111139
{
112140
ObjectMapper m = new ObjectMapper();
113141
m.addMixIn(StringWrapper.class, StringWrapperMixIn.class);
114142
StringWrapper result = m.readValue("\"a\"", StringWrapper.class);
115143
assertEquals("a", result._value);
116144
}
145+
146+
// [databind#2020]
147+
/*
148+
public void testFactoryPropertyMixin() throws Exception
149+
{
150+
ObjectMapper objectMapper = new ObjectMapper();
151+
objectMapper.addMixIn(Pair2020.class, MyPairMixIn8.class);
152+
153+
String doc = aposToQuotes( "{'value0' : 456, 'value1' : 789}");
154+
Pair2020 pair2 = objectMapper.readValue(doc, Pair2020.class);
155+
assertEquals(456, pair2.x);
156+
assertEquals(789, pair2.y);
157+
}
158+
*/
117159
}

src/test/java/com/fasterxml/jackson/databind/introspect/TestMixinMerging.java renamed to src/test/java/com/fasterxml/jackson/databind/mixins/TestMixinMerging.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.fasterxml.jackson.databind.introspect;
1+
package com.fasterxml.jackson.databind.mixins;
22

33
import com.fasterxml.jackson.annotation.JsonProperty;
44

0 commit comments

Comments
 (0)