Skip to content

Commit b7b7bd1

Browse files
committed
Fix FasterXML#1751: allow non-String scalar Type Ids with @JsonTypeInfo
1 parent 02c625f commit b7b7bd1

File tree

3 files changed

+66
-17
lines changed

3 files changed

+66
-17
lines changed

release-notes/VERSION-2.x

+5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ Project: jackson-databind
44
=== Releases ===
55
------------------------------------------------------------------------
66

7+
2.14.2 (not yet released)
8+
9+
#1751: `@JsonTypeInfo` does not work if the Type Id is an Integer value
10+
(reported by @marvin-we)
11+
712
2.14.1 (21-Nov-2022)
813

914
#3655: `Enum` values can not be read from single-element array even with

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

+5-2
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,9 @@ protected String _locateTypeId(JsonParser p, DeserializationContext ctxt) throws
144144
}
145145
// And then type id as a String
146146
JsonToken t = p.nextToken();
147-
if (t == JsonToken.VALUE_STRING) {
147+
if ((t == JsonToken.VALUE_STRING)
148+
// 25-Nov-2022, tatu: [databind#1761] Also accept other scalars
149+
|| ((t != null) && t.isScalarValue())) {
148150
String result = p.getText();
149151
p.nextToken();
150152
return result;
@@ -162,7 +164,8 @@ protected String _locateTypeId(JsonParser p, DeserializationContext ctxt) throws
162164
// 11-Nov-202, tatu: points to wrong place since we don't pass JsonParser
163165
// we actually use (which is usually TokenBuffer created)... should fix
164166
ctxt.reportWrongTokenException(baseType(), JsonToken.VALUE_STRING,
165-
"need JSON String that contains type id (for subtype of %s)", baseTypeName());
167+
"need JSON String, Number of Boolean that contains type id (for subtype of %s)",
168+
baseTypeName());
166169
return null;
167170
}
168171

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

+56-15
Original file line numberDiff line numberDiff line change
@@ -117,29 +117,43 @@ static class Issue506DateBean {
117117
@JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "type2")
118118
public Date date;
119119
}
120-
120+
121121
static class Issue506NumberBean
122122
{
123123
@JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "type3")
124124
@JsonSubTypes({ @Type(Long.class),
125125
@Type(Integer.class) })
126126
public Number number;
127127
}
128-
128+
129+
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_ARRAY)
130+
@JsonSubTypes({ @Type(value = Issue1751ArrImpl.class, name = "0") })
131+
static interface Issue1751ArrBase { }
132+
133+
static class Issue1751ArrImpl implements Issue1751ArrBase { }
134+
135+
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY,
136+
property = "type")
137+
@JsonSubTypes({ @Type(value = Issue1751PropImpl.class, name = "1") })
138+
static interface Issue1751PropBase { }
139+
140+
static class Issue1751PropImpl implements Issue1751PropBase { }
141+
129142
/*
130143
/**********************************************************
131144
/* Unit tests
132145
/**********************************************************
133146
*/
147+
148+
private final ObjectMapper MAPPER = newJsonMapper();
134149

135150
/**
136151
* First things first, let's ensure we can serialize using
137152
* class name, written as main-level property name
138153
*/
139154
public void testSimpleClassAsProperty() throws Exception
140155
{
141-
ObjectMapper m = new ObjectMapper();
142-
Animal a = m.readValue(asJSONObjectValueString("@classy", Cat.class.getName(),
156+
Animal a = MAPPER.readValue(asJSONObjectValueString("@classy", Cat.class.getName(),
143157
"furColor", "tabby", "name", "Garfield"), Animal.class);
144158
assertNotNull(a);
145159
assertEquals(Cat.class, a.getClass());
@@ -181,7 +195,7 @@ public void testTypeAsArray() throws Exception
181195
// Use basic Animal as contents of a regular List
182196
public void testListAsArray() throws Exception
183197
{
184-
ObjectMapper m = new ObjectMapper();
198+
ObjectMapper m = MAPPER;
185199
// This time using PROPERTY style (default) again
186200
String JSON = "[\n"
187201
+asJSONObjectValueString(m, "@classy", Cat.class.getName(), "name", "Hello", "furColor", "white")
@@ -213,11 +227,10 @@ public void testListAsArray() throws Exception
213227

214228
public void testCagedAnimal() throws Exception
215229
{
216-
ObjectMapper m = new ObjectMapper();
217-
String jsonCat = asJSONObjectValueString(m, "@classy", Cat.class.getName(), "name", "Nilson", "furColor", "black");
230+
String jsonCat = asJSONObjectValueString(MAPPER, "@classy", Cat.class.getName(), "name", "Nilson", "furColor", "black");
218231
String JSON = "{\"animal\":"+jsonCat+"}";
219232

220-
AnimalContainer cont = m.readValue(JSON, AnimalContainer.class);
233+
AnimalContainer cont = MAPPER.readValue(JSON, AnimalContainer.class);
221234
assertNotNull(cont);
222235
Animal a = cont.animal;
223236
assertNotNull(a);
@@ -232,7 +245,7 @@ public void testCagedAnimal() throws Exception
232245
*/
233246
public void testAbstractEmptyBaseClass() throws Exception
234247
{
235-
DummyBase result = new ObjectMapper().readValue(
248+
DummyBase result = MAPPER.readValue(
236249
"[\""+DummyImpl.class.getName()+"\",{\"x\":3}]", DummyBase.class);
237250
assertNotNull(result);
238251
assertEquals(DummyImpl.class, result.getClass());
@@ -245,10 +258,9 @@ public void testIssue506WithDate() throws Exception
245258
Issue506DateBean input = new Issue506DateBean();
246259
input.date = new Date(1234L);
247260

248-
ObjectMapper mapper = new ObjectMapper();
249-
String json = mapper.writeValueAsString(input);
261+
String json = MAPPER.writeValueAsString(input);
250262

251-
Issue506DateBean output = mapper.readValue(json, Issue506DateBean.class);
263+
Issue506DateBean output = MAPPER.readValue(json, Issue506DateBean.class);
252264
assertEquals(input.date, output.date);
253265
}
254266

@@ -258,13 +270,42 @@ public void testIssue506WithNumber() throws Exception
258270
Issue506NumberBean input = new Issue506NumberBean();
259271
input.number = Long.valueOf(4567L);
260272

261-
ObjectMapper mapper = new ObjectMapper();
262-
String json = mapper.writeValueAsString(input);
273+
String json = MAPPER.writeValueAsString(input);
263274

264-
Issue506NumberBean output = mapper.readValue(json, Issue506NumberBean.class);
275+
Issue506NumberBean output = MAPPER.readValue(json, Issue506NumberBean.class);
265276
assertEquals(input.number, output.number);
266277
}
267278

279+
// [databind#1751]: allow ints as ids too
280+
public void testIntAsTypeId1751Array() throws Exception
281+
{
282+
Issue1751ArrBase value;
283+
284+
// Should allow both String and Int:
285+
value = MAPPER.readValue("[0, { }]", Issue1751ArrBase.class);
286+
assertNotNull(value);
287+
assertEquals(Issue1751ArrImpl.class, value.getClass());
288+
289+
value = MAPPER.readValue("[\"0\", { }]", Issue1751ArrBase.class);
290+
assertNotNull(value);
291+
assertEquals(Issue1751ArrImpl.class, value.getClass());
292+
}
293+
294+
// [databind#1751]: allow ints as ids too
295+
public void testIntAsTypeId1751Prop() throws Exception
296+
{
297+
Issue1751PropBase value;
298+
299+
// Should allow both String and Int:
300+
value = MAPPER.readValue("{\"type\" : \"1\"}", Issue1751PropBase.class);
301+
assertNotNull(value);
302+
assertEquals(Issue1751PropImpl.class, value.getClass());
303+
304+
value = MAPPER.readValue("{\"type\" : 1}", Issue1751PropBase.class);
305+
assertNotNull(value);
306+
assertEquals(Issue1751PropImpl.class, value.getClass());
307+
}
308+
268309
// [databind#2467]: Allow missing "content" for as-array deserialization
269310
public void testTypeAsArrayWithNullableType() throws Exception
270311
{

0 commit comments

Comments
 (0)