Skip to content

Commit 5d1f645

Browse files
committed
Fixed #2753
1 parent ec29f71 commit 5d1f645

4 files changed

Lines changed: 109 additions & 18 deletions

File tree

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

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -338,8 +338,6 @@ public boolean useForType(JavaType t)
338338
}
339339
}
340340

341-
342-
343341
/*
344342
/**********************************************************
345343
/* Internal constants, singletons
@@ -1837,7 +1835,7 @@ public void registerSubtypes(Collection<Class<?>> subtypes) {
18371835
/**
18381836
* Convenience method that is equivalent to calling
18391837
*<pre>
1840-
* enableDefaultTyping(ptv, DefaultTyping.OBJECT_AND_NON_CONCRETE);
1838+
* activateDefaultTyping(ptv, DefaultTyping.OBJECT_AND_NON_CONCRETE);
18411839
*</pre>
18421840
*<p>
18431841
* NOTE: choice of {@link PolymorphicTypeValidator} to pass is critical for security
@@ -1855,7 +1853,7 @@ public ObjectMapper activateDefaultTyping(PolymorphicTypeValidator ptv) {
18551853
/**
18561854
* Convenience method that is equivalent to calling
18571855
*<pre>
1858-
* enableDefaultTyping(ptv, dti, JsonTypeInfo.As.WRAPPER_ARRAY);
1856+
* activateDefaultTyping(ptv, dti, JsonTypeInfo.As.WRAPPER_ARRAY);
18591857
*</pre>
18601858
*<p>
18611859
* NOTE: choice of {@link PolymorphicTypeValidator} to pass is critical for security
@@ -1874,11 +1872,11 @@ public ObjectMapper activateDefaultTyping(PolymorphicTypeValidator ptv,
18741872
}
18751873

18761874
/**
1877-
* Method for enabling automatic inclusion of type information, needed
1878-
* for proper deserialization of polymorphic types (unless types
1875+
* Method for enabling automatic inclusion of type information ("Default Typing"),
1876+
* needed for proper deserialization of polymorphic types (unless types
18791877
* have been annotated with {@link com.fasterxml.jackson.annotation.JsonTypeInfo}).
18801878
*<P>
1881-
* NOTE: use of <code>JsonTypeInfo.As#EXTERNAL_PROPERTY</code> <b>NOT SUPPORTED</b>;
1879+
* NOTE: use of {@code JsonTypeInfo.As#EXTERNAL_PROPERTY} <b>NOT SUPPORTED</b>;
18821880
* and attempts of do so will throw an {@link IllegalArgumentException} to make
18831881
* this limitation explicit.
18841882
*<p>
@@ -1910,8 +1908,8 @@ public ObjectMapper activateDefaultTyping(PolymorphicTypeValidator ptv,
19101908
}
19111909

19121910
/**
1913-
* Method for enabling automatic inclusion of type information -- needed
1914-
* for proper deserialization of polymorphic types (unless types
1911+
* Method for enabling automatic inclusion of type information ("Default Typing")
1912+
* -- needed for proper deserialization of polymorphic types (unless types
19151913
* have been annotated with {@link com.fasterxml.jackson.annotation.JsonTypeInfo}) --
19161914
* using "As.PROPERTY" inclusion mechanism and specified property name
19171915
* to use for inclusion (default being "@class" since default type information
@@ -1954,8 +1952,8 @@ public ObjectMapper deactivateDefaultTyping() {
19541952
}
19551953

19561954
/**
1957-
* Method for enabling automatic inclusion of type information, using
1958-
* specified handler object for determining which types this affects,
1955+
* Method for enabling automatic inclusion of type information ("Default Typing"),
1956+
* using specified handler object for determining which types this affects,
19591957
* as well as details of how information is embedded.
19601958
*<p>
19611959
* NOTE: use of Default Typing can be a potential security risk if incoming

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

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,10 @@ public TypeSerializer buildTypeSerializer(SerializationConfig config,
8484
// 03-Oct-2016, tatu: As per [databind#1395] better prevent use for primitives,
8585
// regardless of setting
8686
if (baseType.isPrimitive()) {
87-
return null;
87+
// 19-Jun-2020, tatu: But for [databind#2753], allow overriding
88+
if (!allowPrimitiveTypes(config, baseType)) {
89+
return null;
90+
}
8891
}
8992
TypeIdResolver idRes = idResolver(config, baseType, subTypeValidator(config),
9093
subtypes, true, false);
@@ -118,7 +121,10 @@ public TypeDeserializer buildTypeDeserializer(DeserializationConfig config,
118121
// 03-Oct-2016, tatu: As per [databind#1395] better prevent use for primitives,
119122
// regardless of setting
120123
if (baseType.isPrimitive()) {
121-
return null;
124+
// 19-Jun-2020, tatu: But for [databind#2753], allow overriding
125+
if (!allowPrimitiveTypes(config, baseType)) {
126+
return null;
127+
}
122128
}
123129

124130
// 27-Apr-2019, tatu: Part of [databind#2195]; must first check whether any subtypes
@@ -151,7 +157,6 @@ public TypeDeserializer buildTypeDeserializer(DeserializationConfig config,
151157
protected JavaType defineDefaultImpl(DeserializationConfig config, JavaType baseType) {
152158
JavaType defaultImpl;
153159
if (_defaultImpl == null) {
154-
//Fis of issue #955
155160
if (config.isEnabled(MapperFeature.USE_BASE_TYPE_AS_DEFAULT_IMPL) && !baseType.isAbstract()) {
156161
defaultImpl = baseType;
157162
} else {
@@ -332,4 +337,31 @@ protected PolymorphicTypeValidator reportInvalidBaseType(MapperConfig<?> config,
332337
ClassUtil.classNameOf(ptv), ClassUtil.classNameOf(baseType.getRawClass()))
333338
);
334339
}
340+
341+
/*
342+
/**********************************************************
343+
/* Overridable helper methods
344+
/**********************************************************
345+
*/
346+
347+
/**
348+
* Overridable helper method that is called to determine whether type serializers
349+
* and type deserializers may be created even if base type is Java {@code primitive}
350+
* type.
351+
* Default implementation simply returns {@code false} (since primitive types can not
352+
* be sub-classed, are never polymorphic) but custom implementations
353+
* may change the logic for some special cases.
354+
*
355+
* @param config Currently active configuration
356+
* @param baseType Primitive base type for property being handled
357+
*
358+
* @return True if type (de)serializer may be created even if base type is Java
359+
* {@code primitive} type; false if not
360+
*
361+
* @since 2.11.1
362+
*/
363+
protected boolean allowPrimitiveTypes(MapperConfig<?> config,
364+
JavaType baseType) {
365+
return false;
366+
}
335367
}

src/main/java/com/fasterxml/jackson/databind/ser/std/BeanSerializerBase.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ public void resolve(SerializerProvider provider)
338338
}
339339
}
340340
}
341-
341+
342342
if (prop.hasSerializer()) {
343343
continue;
344344
}
@@ -360,9 +360,8 @@ public void resolve(SerializerProvider provider)
360360
}
361361
}
362362
ser = provider.findValueSerializer(type, prop);
363-
/* 04-Feb-2010, tatu: We may have stashed type serializer for content types
364-
* too, earlier; if so, it's time to connect the dots here:
365-
*/
363+
// 04-Feb-2010, tatu: We may have stashed type serializer for content types
364+
// too, earlier; if so, it's time to connect the dots here:
366365
if (type.isContainerType()) {
367366
TypeSerializer typeSer = type.getContentType().getTypeHandler();
368367
if (typeSer != null) {
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package com.fasterxml.jackson.databind.jsontype.deftyping;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
6+
import com.fasterxml.jackson.annotation.*;
7+
8+
import com.fasterxml.jackson.databind.*;
9+
import com.fasterxml.jackson.databind.annotation.JsonTypeResolver;
10+
import com.fasterxml.jackson.databind.cfg.MapperConfig;
11+
import com.fasterxml.jackson.databind.jsontype.impl.StdTypeResolverBuilder;
12+
13+
public class DefaultTypeResolverForLong2753Test extends BaseMapTest
14+
{
15+
static class Data {
16+
private Long key;
17+
18+
@JsonCreator
19+
private Data(@JsonProperty("key") Long key) {
20+
this.key = key;
21+
}
22+
23+
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
24+
@JsonTypeResolver(MyTypeResolverBuilder.class)
25+
public long key() {
26+
return key;
27+
}
28+
}
29+
30+
static class MyTypeResolverBuilder extends StdTypeResolverBuilder {
31+
@Override
32+
protected boolean allowPrimitiveTypes(MapperConfig<?> config,
33+
JavaType baseType) {
34+
return true;
35+
}
36+
}
37+
38+
public void testDefaultTypingWithLong() throws Exception
39+
{
40+
Data data = new Data(1L);
41+
Map<String, Object> mapData = new HashMap<>();
42+
mapData.put("longInMap", 2L);
43+
mapData.put("longAsField", data);
44+
45+
// Configure Jackson to preserve types
46+
// StdTypeResolverBuilder resolver = new MyTypeResolverBuilder();
47+
// resolver.init(JsonTypeInfo.Id.CLASS, null);
48+
// resolver.inclusion(JsonTypeInfo.As.PROPERTY);
49+
// resolver.typeProperty("__t");
50+
ObjectMapper mapper = jsonMapperBuilder()
51+
// .setDefaultTyping(resolver)
52+
.enable(SerializationFeature.INDENT_OUTPUT)
53+
.build();
54+
55+
// Serialize
56+
String json = mapper.writeValueAsString(mapData);
57+
//System.err.println("JSON:\n"+json);
58+
Map<?,?> result = mapper.readValue(json, Map.class);
59+
assertNotNull(result);
60+
assertEquals(2, result.size());
61+
}
62+
}

0 commit comments

Comments
 (0)