Skip to content

Commit ed7d0a8

Browse files
committed
Some more work towards #2539 for 3.x -- still need tests
1 parent 08f2e37 commit ed7d0a8

File tree

5 files changed

+85
-57
lines changed

5 files changed

+85
-57
lines changed

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

+19
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,25 @@ public PropertyName findRootName(Class<?> rawRootType) {
499499
return _config.findRootName(this, rawRootType);
500500
}
501501

502+
/**
503+
* Method that can be used to see whether there is an explicitly registered deserializer
504+
* for given type: this is true for supported JDK types, as well as third-party types
505+
* for which {@code Module} provides support but is NOT true (that is, returns {@code false})
506+
* for POJO types for which {@code BeanDeserializer} is generated based on discovered
507+
* properties.
508+
*<p>
509+
* Note that it is up to {@code Module}s to implement support for this method: some
510+
* do (like basic {@code SimpleModule}).
511+
*
512+
* @param valueType Type-erased type to check
513+
*
514+
* @return True if this factory has explicit (non-POJO) deserializer for specified type,
515+
* or has a provider (of type {@link Deserializers}) that has.
516+
*/
517+
public boolean hasExplicitDeserializerFor(Class<?> valueType) {
518+
return _factory.hasExplicitDeserializerFor(this, valueType);
519+
}
520+
502521
/*
503522
/**********************************************************************
504523
/* Public API, value deserializer access

src/main/java/com/fasterxml/jackson/databind/jsontype/BasicPolymorphicTypeValidator.java

+8-12
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import com.fasterxml.jackson.databind.DatabindContext;
77
import com.fasterxml.jackson.databind.JavaType;
88
import com.fasterxml.jackson.databind.JsonMappingException;
9+
import com.fasterxml.jackson.databind.DeserializationContext;
910

1011
/**
1112
* Standard {@link BasicPolymorphicTypeValidator} implementation that users may want
@@ -18,8 +19,6 @@
1819
* For example:
1920
*<pre>
2021
*</pre>
21-
*
22-
* @since 2.10
2322
*/
2423
public class BasicPolymorphicTypeValidator
2524
extends PolymorphicTypeValidator.Base
@@ -166,8 +165,6 @@ public boolean match(DatabindContext ctxt, Class<?> clazz) {
166165
* @param matcher Custom matcher to apply to base type
167166
*
168167
* @return This Builder to allow call chaining
169-
*
170-
* @since 2.11
171168
*/
172169
public Builder allowIfBaseType(final TypeMatcher matcher) {
173170
return _appendBaseMatcher(matcher);
@@ -268,8 +265,6 @@ public boolean match(DatabindContext ctxt, String clazzName) {
268265
* @param matcher Custom matcher to apply to resolved subtype
269266
*
270267
* @return This Builder to allow call chaining
271-
*
272-
* @since 2.11
273268
*/
274269
public Builder allowIfSubType(final TypeMatcher matcher) {
275270
return _appendSubClassMatcher(matcher);
@@ -286,8 +281,6 @@ public Builder allowIfSubType(final TypeMatcher matcher) {
286281
* NOTE: not used with other Java collection types ({@link java.util.List}s,
287282
* {@link java.util.Collection}s), mostly since use of generic types as polymorphic
288283
* values is not (well) supported.
289-
*
290-
* @since 2.11
291284
*/
292285
public Builder allowIfSubTypeIsArray() {
293286
return _appendSubClassMatcher(new TypeMatcher() {
@@ -316,14 +309,17 @@ public boolean match(DatabindContext ctxt, Class<?> clazz) {
316309
* NOTE: Modules need to provide support for detection so if 3rd party types do not seem to
317310
* be supported, Module in question may need to be updated to indicate existence of explicit
318311
* deserializers.
319-
*
320-
* @since 2.11
321312
*/
322313
public Builder allowSubTypesWithExplicitDeserializer() {
323314
return _appendSubClassMatcher(new TypeMatcher() {
324315
@Override
325-
public boolean match(DatabindContext ctxt, Class<?> clazz) {
326-
return clazz.isArray();
316+
public boolean match(DatabindContext ctxt, Class<?> valueType) {
317+
// First things first: "peel off" array type (since Array types are provided
318+
// by JDK and can not be gadget types)
319+
while (valueType.isArray()) {
320+
valueType = valueType.getComponentType();
321+
}
322+
return ((DeserializationContext) ctxt).hasExplicitDeserializerFor(valueType);
327323
}
328324
});
329325
}

src/main/java/com/fasterxml/jackson/databind/jsontype/NoneShallPassValidator.java

+33-20
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,15 @@
33
import com.fasterxml.jackson.databind.DatabindContext;
44
import com.fasterxml.jackson.databind.JavaType;
55
import com.fasterxml.jackson.databind.JsonMappingException;
6+
import com.fasterxml.jackson.databind.util.ClassUtil;
67

78
/**
89
* Default {@link PolymorphicTypeValidator} used unless explicit one is constructed.
9-
* Denies use of all types so isn't very useful as base.
10+
* Denies use of most types so isn't very useful as base, as it only allows:
11+
* <ul>
12+
* <li>Enums
13+
* </li>
14+
* </ul>
1015
*/
1116
public class NoneShallPassValidator
1217
extends PolymorphicTypeValidator
@@ -16,17 +21,12 @@ public class NoneShallPassValidator
1621

1722
@Override
1823
public Validity validateBaseType(DatabindContext ctxt, JavaType baseType)
19-
throws JsonMappingException {
20-
/* 24-Apr-2019, tatu: We do need to make it restrictive, BUT... as of now
21-
* tests would fail; need to get back to that right after 2.10
22-
return Validity.DENIED;
23-
*/
24-
/*
25-
if (baseType.hasRawClass(Object.class)) {
26-
return Validity.DENIED;
27-
}
28-
*/
29-
return Validity.ALLOWED;
24+
throws JsonMappingException
25+
{
26+
// Actually let's not block any particular base type, just mark as
27+
// indeterminate to only base on actual subtype
28+
29+
return Validity.INDETERMINATE;
3030
}
3131

3232
@Override
@@ -37,16 +37,29 @@ public Validity validateSubClassName(DatabindContext ctxt,
3737

3838
@Override
3939
public Validity validateSubType(DatabindContext ctxt, JavaType baseType,
40-
JavaType subType) {
41-
/* 24-Apr-2019, tatu: We do need to make it restrictive, BUT... as of now
42-
* tests would fail; need to get back to that right after 2.10
43-
return Validity.DENIED;
44-
*/
45-
/*
46-
if (baseType.hasRawClass(Object.class)) {
40+
JavaType subType)
41+
{
42+
// Very small set of allowed types:
43+
//
44+
// 1. Enums
45+
// 2. Primitives, their wrappers
46+
47+
if (subType.isEnumType()) {
48+
return Validity.ALLOWED;
49+
}
50+
if (ClassUtil.primitiveType(subType.getRawClass()) != null) {
51+
return Validity.ALLOWED;
52+
}
53+
54+
// But aside from that actually only allow if base type not too generic
55+
final Class<?> rawBase = baseType.getRawClass();
56+
if ((rawBase == Object.class)
57+
|| (rawBase == Object.class)
58+
|| (rawBase == Object.class)
59+
) {
4760
return Validity.DENIED;
4861
}
49-
*/
62+
5063
return Validity.ALLOWED;
5164
}
5265
}

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

+21-24
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import com.fasterxml.jackson.databind.BaseMapTest;
88
import com.fasterxml.jackson.databind.ObjectMapper;
9+
import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
910

1011
/**
1112
* Testing to verify that {@link JsonTypeInfo} works
@@ -81,36 +82,37 @@ static class OtherBean {
8182
/**********************************************************
8283
*/
8384

85+
final ObjectMapper MAPPER = jsonMapperBuilder()
86+
.polymorphicTypeValidator(new NoCheckSubTypeValidator())
87+
.build();
88+
8489
public void testSimpleField() throws Exception
8590
{
86-
ObjectMapper mapper = new ObjectMapper();
87-
String json = mapper.writeValueAsString(new FieldWrapperBean(new StringWrapper("foo")));
91+
String json = MAPPER.writeValueAsString(new FieldWrapperBean(new StringWrapper("foo")));
8892
//System.out.println("JSON/field+object == "+json);
89-
FieldWrapperBean bean = mapper.readValue(json, FieldWrapperBean.class);
93+
FieldWrapperBean bean = MAPPER.readValue(json, FieldWrapperBean.class);
9094
assertNotNull(bean.value);
9195
assertEquals(StringWrapper.class, bean.value.getClass());
9296
assertEquals(((StringWrapper) bean.value).str, "foo");
9397
}
9498

9599
public void testSimpleMethod() throws Exception
96100
{
97-
ObjectMapper mapper = new ObjectMapper();
98-
String json = mapper.writeValueAsString(new FieldWrapperBean(new IntWrapper(37)));
101+
String json = MAPPER.writeValueAsString(new FieldWrapperBean(new IntWrapper(37)));
99102
//System.out.println("JSON/method+object == "+json);
100-
FieldWrapperBean bean = mapper.readValue(json, FieldWrapperBean.class);
103+
FieldWrapperBean bean = MAPPER.readValue(json, FieldWrapperBean.class);
101104
assertNotNull(bean.value);
102105
assertEquals(IntWrapper.class, bean.value.getClass());
103106
assertEquals(((IntWrapper) bean.value).i, 37);
104107
}
105108

106109
public void testSimpleListField() throws Exception
107110
{
108-
ObjectMapper mapper = new ObjectMapper();
109111
FieldWrapperBeanList list = new FieldWrapperBeanList();
110112
list.add(new FieldWrapperBean(new OtherBean()));
111-
String json = mapper.writeValueAsString(list);
113+
String json = MAPPER.writeValueAsString(list);
112114
//System.out.println("JSON/field+list == "+json);
113-
FieldWrapperBeanList result = mapper.readValue(json, FieldWrapperBeanList.class);
115+
FieldWrapperBeanList result = MAPPER.readValue(json, FieldWrapperBeanList.class);
114116
assertNotNull(result);
115117
assertEquals(1, result.size());
116118
FieldWrapperBean bean = list.get(0);
@@ -121,13 +123,12 @@ public void testSimpleListField() throws Exception
121123

122124
public void testSimpleListMethod() throws Exception
123125
{
124-
ObjectMapper mapper = new ObjectMapper();
125126
MethodWrapperBeanList list = new MethodWrapperBeanList();
126127
list.add(new MethodWrapperBean(new BooleanValue(true)));
127128
list.add(new MethodWrapperBean(new StringWrapper("x")));
128129
list.add(new MethodWrapperBean(new OtherBean()));
129-
String json = mapper.writeValueAsString(list);
130-
MethodWrapperBeanList result = mapper.readValue(json, MethodWrapperBeanList.class);
130+
String json = MAPPER.writeValueAsString(list);
131+
MethodWrapperBeanList result = MAPPER.readValue(json, MethodWrapperBeanList.class);
131132
assertNotNull(result);
132133
assertEquals(3, result.size());
133134
MethodWrapperBean bean = result.get(0);
@@ -142,11 +143,10 @@ public void testSimpleListMethod() throws Exception
142143

143144
public void testSimpleArrayField() throws Exception
144145
{
145-
ObjectMapper mapper = new ObjectMapper();
146146
FieldWrapperBeanArray array = new FieldWrapperBeanArray(new
147147
FieldWrapperBean[] { new FieldWrapperBean(new BooleanValue(true)) });
148-
String json = mapper.writeValueAsString(array);
149-
FieldWrapperBeanArray result = mapper.readValue(json, FieldWrapperBeanArray.class);
148+
String json = MAPPER.writeValueAsString(array);
149+
FieldWrapperBeanArray result = MAPPER.readValue(json, FieldWrapperBeanArray.class);
150150
assertNotNull(result);
151151
FieldWrapperBean[] beans = result.beans;
152152
assertEquals(1, beans.length);
@@ -157,11 +157,10 @@ public void testSimpleArrayField() throws Exception
157157

158158
public void testSimpleArrayMethod() throws Exception
159159
{
160-
ObjectMapper mapper = new ObjectMapper();
161160
MethodWrapperBeanArray array = new MethodWrapperBeanArray(new
162161
MethodWrapperBean[] { new MethodWrapperBean(new StringWrapper("A")) });
163-
String json = mapper.writeValueAsString(array);
164-
MethodWrapperBeanArray result = mapper.readValue(json, MethodWrapperBeanArray.class);
162+
String json = MAPPER.writeValueAsString(array);
163+
MethodWrapperBeanArray result = MAPPER.readValue(json, MethodWrapperBeanArray.class);
165164
assertNotNull(result);
166165
MethodWrapperBean[] beans = result.beans;
167166
assertEquals(1, beans.length);
@@ -172,11 +171,10 @@ public void testSimpleArrayMethod() throws Exception
172171

173172
public void testSimpleMapField() throws Exception
174173
{
175-
ObjectMapper mapper = new ObjectMapper();
176174
FieldWrapperBeanMap map = new FieldWrapperBeanMap();
177175
map.put("foop", new FieldWrapperBean(new IntWrapper(13)));
178-
String json = mapper.writeValueAsString(map);
179-
FieldWrapperBeanMap result = mapper.readValue(json, FieldWrapperBeanMap.class);
176+
String json = MAPPER.writeValueAsString(map);
177+
FieldWrapperBeanMap result = MAPPER.readValue(json, FieldWrapperBeanMap.class);
180178
assertNotNull(result);
181179
assertEquals(1, result.size());
182180
FieldWrapperBean bean = result.get("foop");
@@ -188,11 +186,10 @@ public void testSimpleMapField() throws Exception
188186

189187
public void testSimpleMapMethod() throws Exception
190188
{
191-
ObjectMapper mapper = new ObjectMapper();
192189
MethodWrapperBeanMap map = new MethodWrapperBeanMap();
193190
map.put("xyz", new MethodWrapperBean(new BooleanValue(true)));
194-
String json = mapper.writeValueAsString(map);
195-
MethodWrapperBeanMap result = mapper.readValue(json, MethodWrapperBeanMap.class);
191+
String json = MAPPER.writeValueAsString(map);
192+
MethodWrapperBeanMap result = MAPPER.readValue(json, MethodWrapperBeanMap.class);
196193
assertNotNull(result);
197194
assertEquals(1, result.size());
198195
MethodWrapperBean bean = result.get("xyz");

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

+4-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import com.fasterxml.jackson.annotation.JsonTypeInfo;
99
import com.fasterxml.jackson.databind.BaseMapTest;
1010
import com.fasterxml.jackson.databind.ObjectMapper;
11+
import com.fasterxml.jackson.databind.testutil.NoCheckSubTypeValidator;
1112

1213
public class TestScalars extends BaseMapTest
1314
{
@@ -49,7 +50,9 @@ public ScalarList add(Object v) {
4950
/**********************************************************************
5051
*/
5152

52-
final ObjectMapper MAPPER = newJsonMapper();
53+
final ObjectMapper MAPPER = jsonMapperBuilder()
54+
.polymorphicTypeValidator(new NoCheckSubTypeValidator())
55+
.build();
5356

5457
/**
5558
* Ensure that per-property dynamic types work, both for "native" types

0 commit comments

Comments
 (0)