Skip to content

Commit ef628ca

Browse files
committed
Backport #2761 in 2.12
1 parent 5299c1a commit ef628ca

File tree

4 files changed

+64
-67
lines changed

4 files changed

+64
-67
lines changed

release-notes/CREDITS-2.x

+4
Original file line numberDiff line numberDiff line change
@@ -1174,3 +1174,7 @@ David Bidorff (bidorffOL@github)
11741174
Jendrik Johannes (jjohannes@github)
11751175
* Contributed #2726: Add Gradle Module Metadata for version alignment with Gradle 6
11761176
(2.12.0)
1177+
1178+
Swayam Raina (swayamraina@github)
1179+
* Contributed #2761: Support multiple names in `JsonSubType.Type`
1180+
(2.12.0)

release-notes/VERSION-2.x

+2
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ Project: jackson-databind
3939
#2732: Allow `JsonNode` auto-convert into `ArrayNode` if duplicates found (for XML)
4040
#2733: Allow values of "untyped" auto-convert into `List` if duplicates found (for XML)
4141
#2751: Add `ValueInstantiator.createContextual(...)
42+
#2761: Support multiple names in `JsonSubType.Type`
43+
(contributed by Swayam R)
4244
#2776: Explicitly fail (de)serialization of `org.joda.time.*` types in absence of registered
4345
custom (de)serializers
4446
#2784: Trailing zeros are stripped when deserializing BigDecimal values inside a

src/main/java/com/fasterxml/jackson/databind/introspect/JacksonAnnotationIntrospector.java

+1
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,7 @@ public List<NamedType> findSubtypes(Annotated a)
592592
ArrayList<NamedType> result = new ArrayList<NamedType>(types.length);
593593
for (JsonSubTypes.Type type : types) {
594594
result.add(new NamedType(type.value(), type.name()));
595+
// [databind#2761]: alternative set of names to use
595596
for (String name : type.names()) {
596597
result.add(new NamedType(type.value(), name));
597598
}

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

+57-67
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,17 @@
22

33
import com.fasterxml.jackson.annotation.JsonSubTypes;
44
import com.fasterxml.jackson.annotation.JsonTypeInfo;
5+
56
import com.fasterxml.jackson.databind.BaseMapTest;
67
import com.fasterxml.jackson.databind.ObjectMapper;
78
import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException;
8-
import org.junit.Assert;
99

1010
import java.util.List;
1111

12-
13-
/**
14-
* Tests for sub-types id user uses,
15-
* 1. only names in all sub-types
16-
* 2. 'names' for multi-keys while 'name' for singular keys
17-
*
18-
* [ annotations#171 ]
19-
* As per this feature, keys holding similar java object types can be incorporated
20-
* within the same annotation.
21-
* See this <a href="https://github.com/FasterXML/jackson-annotations/issues/171">issue/improvement</a>
22-
*/
23-
public class TestMultipleTypeNames extends BaseMapTest {
24-
25-
// serializer-deserializer
26-
private final ObjectMapper MAPPER = objectMapper();
27-
12+
// Tests for [databind#2761] (and [annotations#171]
13+
public class TestMultipleTypeNames extends BaseMapTest
14+
{
15+
private final ObjectMapper MAPPER = newJsonMapper();
2816

2917
// common classes
3018
static class MultiTypeName { }
@@ -39,10 +27,6 @@ static class B extends MultiTypeName {
3927
public float getY() { return y; }
4028
}
4129

42-
43-
44-
45-
4630
// data for test 1
4731
static class WrapperForNamesTest {
4832
private List<BaseForNamesTest> base;
@@ -53,49 +37,19 @@ static class BaseForNamesTest {
5337
private String type;
5438
public String getType() { return type; }
5539

56-
@JsonTypeInfo (
40+
@JsonTypeInfo(
5741
use = JsonTypeInfo.Id.NAME,
5842
include = JsonTypeInfo.As.EXTERNAL_PROPERTY,
5943
property = "type"
6044
)
61-
@JsonSubTypes (value = {
45+
@JsonSubTypes(value = {
6246
@JsonSubTypes.Type(value = A.class, names = "a"),
6347
@JsonSubTypes.Type(value = B.class, names = {"b","c"}),
6448
})
6549
private MultiTypeName data;
6650
public MultiTypeName getData() { return data; }
6751
}
6852

69-
public void testOnlyNames () throws Exception {
70-
String json;
71-
WrapperForNamesTest w;
72-
73-
// TC 1 : all KV serialisation
74-
json = "{\"base\": [{\"type\":\"a\", \"data\": {\"x\": 5}}, {\"type\":\"b\", \"data\": {\"y\": 3.1}}, {\"type\":\"c\", \"data\": {\"y\": 33.8}}]}";
75-
w = MAPPER.readValue(json, WrapperForNamesTest.class);
76-
Assert.assertNotNull(w);
77-
Assert.assertEquals(3, w.base.size());
78-
Assert.assertTrue(w.base.get(0).data instanceof A);
79-
Assert.assertEquals(5l, ((A) w.base.get(0).data).x);
80-
Assert.assertTrue(w.base.get(1).data instanceof B);
81-
Assert.assertEquals(3.1f, ((B) w.base.get(1).data).y, 0);
82-
Assert.assertTrue(w.base.get(2).data instanceof B);
83-
Assert.assertEquals(33.8f, ((B) w.base.get(2).data).y, 0);
84-
85-
86-
// TC 2 : incorrect serialisation
87-
json = "{\"data\": [{\"type\":\"a\", \"data\": {\"x\": 2.2}}, {\"type\":\"b\", \"data\": {\"y\": 5.3}}, {\"type\":\"c\", \"data\": {\"y\": 9.8}}]}";
88-
try {
89-
MAPPER.readValue(json, WrapperForNamesTest.class);
90-
Assert.fail("This serialisation should fail 'coz of x being float");
91-
} catch (UnrecognizedPropertyException e) {}
92-
}
93-
94-
95-
96-
97-
98-
// data for test 2
9953
static class WrapperForNameAndNamesTest {
10054
private List<BaseForNameAndNamesTest> base;
10155
public List<BaseForNameAndNamesTest> getBase() { return base; }
@@ -105,42 +59,78 @@ static class BaseForNameAndNamesTest {
10559
private String type;
10660
public String getType() { return type; }
10761

108-
@JsonTypeInfo (
62+
@JsonTypeInfo(
10963
use = JsonTypeInfo.Id.NAME,
11064
include = JsonTypeInfo.As.EXTERNAL_PROPERTY,
11165
property = "type"
11266
)
113-
@JsonSubTypes (value = {
67+
@JsonSubTypes(value = {
11468
@JsonSubTypes.Type(value = A.class, name = "a"),
11569
@JsonSubTypes.Type(value = B.class, names = {"b","c"}),
11670
})
11771
private MultiTypeName data;
11872
public MultiTypeName getData() { return data; }
11973
}
12074

121-
public void testNameAndNames () throws Exception {
75+
/*
76+
/**********************************************************
77+
/* Test methods
78+
/**********************************************************
79+
*/
80+
81+
public void testOnlyNames() throws Exception
82+
{
83+
String json;
84+
WrapperForNamesTest w;
85+
86+
// TC 1 : all KV serialisation
87+
json = "{\"base\": [{\"type\":\"a\", \"data\": {\"x\": 5}}, {\"type\":\"b\", \"data\": {\"y\": 3.1}}, {\"type\":\"c\", \"data\": {\"y\": 33.8}}]}";
88+
w = MAPPER.readValue(json, WrapperForNamesTest.class);
89+
assertNotNull(w);
90+
assertEquals(3, w.base.size());
91+
assertTrue(w.base.get(0).data instanceof A);
92+
assertEquals(5l, ((A) w.base.get(0).data).x);
93+
assertTrue(w.base.get(1).data instanceof B);
94+
assertEquals(3.1f, ((B) w.base.get(1).data).y, 0);
95+
assertTrue(w.base.get(2).data instanceof B);
96+
assertEquals(33.8f, ((B) w.base.get(2).data).y, 0);
97+
98+
99+
// TC 2 : incorrect serialisation
100+
json = "{\"data\": [{\"type\":\"a\", \"data\": {\"x\": 2.2}}, {\"type\":\"b\", \"data\": {\"y\": 5.3}}, {\"type\":\"c\", \"data\": {\"y\": 9.8}}]}";
101+
try {
102+
MAPPER.readValue(json, WrapperForNamesTest.class);
103+
fail("This serialisation should fail 'coz of x being float");
104+
} catch (UnrecognizedPropertyException e) {
105+
verifyException(e, "Unrecognized field \"data\"");
106+
}
107+
}
108+
109+
public void testNameAndNames() throws Exception
110+
{
122111
String json;
123112
WrapperForNameAndNamesTest w;
124113

125114
// TC 1 : all KV serialisation
126115
json = "{\"base\": [{\"type\":\"a\", \"data\": {\"x\": 5}}, {\"type\":\"b\", \"data\": {\"y\": 3.1}}, {\"type\":\"c\", \"data\": {\"y\": 33.8}}]}";
127116
w = MAPPER.readValue(json, WrapperForNameAndNamesTest.class);
128-
Assert.assertNotNull(w);
129-
Assert.assertEquals(3, w.base.size());
130-
Assert.assertTrue(w.base.get(0).data instanceof A);
131-
Assert.assertEquals(5l, ((A) w.base.get(0).data).x);
132-
Assert.assertTrue(w.base.get(1).data instanceof B);
133-
Assert.assertEquals(3.1f, ((B) w.base.get(1).data).y, 0);
134-
Assert.assertTrue(w.base.get(2).data instanceof B);
135-
Assert.assertEquals(33.8f, ((B) w.base.get(2).data).y, 0);
117+
assertNotNull(w);
118+
assertEquals(3, w.base.size());
119+
assertTrue(w.base.get(0).data instanceof A);
120+
assertEquals(5l, ((A) w.base.get(0).data).x);
121+
assertTrue(w.base.get(1).data instanceof B);
122+
assertEquals(3.1f, ((B) w.base.get(1).data).y, 0);
123+
assertTrue(w.base.get(2).data instanceof B);
124+
assertEquals(33.8f, ((B) w.base.get(2).data).y, 0);
136125

137126

138127
// TC 2 : incorrect serialisation
139128
json = "{\"data\": [{\"type\":\"a\", \"data\": {\"x\": 2.2}}, {\"type\":\"b\", \"data\": {\"y\": 5.3}}, {\"type\":\"c\", \"data\": {\"y\": 9.8}}]}";
140129
try {
141130
MAPPER.readValue(json, WrapperForNameAndNamesTest.class);
142-
Assert.fail("This serialisation should fail 'coz of x being float");
143-
} catch (UnrecognizedPropertyException e) {}
131+
fail("This serialisation should fail 'coz of x being float");
132+
} catch (UnrecognizedPropertyException e) {
133+
verifyException(e, "Unrecognized field \"data\"");
134+
}
144135
}
145-
146136
}

0 commit comments

Comments
 (0)