Skip to content

Commit dd7258a

Browse files
committed
Fix #2115
1 parent 01c7f58 commit dd7258a

File tree

7 files changed

+52
-9
lines changed

7 files changed

+52
-9
lines changed

release-notes/CREDITS-2.x

+5
Original file line numberDiff line numberDiff line change
@@ -811,5 +811,10 @@ Thibaut Robert (trobert@github)
811811
* Requested #2059: Remove `final` modifier for `TypeFactory`
812812
(2.10.0)
813813
814+
Christopher Smith (chrylis@github)
815+
* Suggested #2115: Support naive deserialization of `Serializable` values as "untyped",
816+
same as `java.lang.Object`
817+
(2.10.0)
818+
814819
Édouard Mercier (edouardmercier@github)
815820
* Requested #2116: Make NumberSerializers.Base public and its inherited classes not final

release-notes/VERSION-2.x

+3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ Project: jackson-databind
88

99
#2059: Remove `final` modifier for `TypeFactory`
1010
(requested by Thibaut R)
11+
#2115: Support naive deserialization of `Serializable` values as "untyped", same
12+
as `java.lang.Object`
13+
(requested by Christopher S)
1114
#2116: Make NumberSerializers.Base public and its inherited classes not final
1215
(requested by Édouard M)
1316

src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.fasterxml.jackson.databind.deser;
22

3+
import java.io.Serializable;
34
import java.util.*;
45
import java.util.concurrent.*;
56
import java.util.concurrent.atomic.AtomicReference;
@@ -8,8 +9,10 @@
89
import com.fasterxml.jackson.annotation.JsonCreator;
910
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
1011
import com.fasterxml.jackson.annotation.JsonCreator.Mode;
12+
1113
import com.fasterxml.jackson.core.JsonLocation;
1214
import com.fasterxml.jackson.core.JsonParser;
15+
1316
import com.fasterxml.jackson.databind.*;
1417
import com.fasterxml.jackson.databind.cfg.DeserializerFactoryConfig;
1518
import com.fasterxml.jackson.databind.cfg.HandlerInstantiator;
@@ -46,6 +49,7 @@ public abstract class BasicDeserializerFactory
4649
private final static Class<?> CLASS_CHAR_SEQUENCE = CharSequence.class;
4750
private final static Class<?> CLASS_ITERABLE = Iterable.class;
4851
private final static Class<?> CLASS_MAP_ENTRY = Map.Entry.class;
52+
private final static Class<?> CLASS_SERIALIZABLE = Serializable.class;
4953

5054
/**
5155
* We need a placeholder for creator properties that don't have name
@@ -1771,8 +1775,8 @@ public JsonDeserializer<?> findDefaultDeserializer(DeserializationContext ctxt,
17711775
throws JsonMappingException
17721776
{
17731777
Class<?> rawType = type.getRawClass();
1774-
// Object ("untyped"), String equivalents:
1775-
if (rawType == CLASS_OBJECT) {
1778+
// Object ("untyped"), and as of 2.10 (see [databind#2115]), `java.io.Serializable`
1779+
if ((rawType == CLASS_OBJECT) || (rawType == CLASS_SERIALIZABLE)) {
17761780
// 11-Feb-2015, tatu: As per [databind#700] need to be careful wrt non-default Map, List.
17771781
DeserializationConfig config = ctxt.getConfig();
17781782
JavaType lt, mt;
@@ -1785,6 +1789,7 @@ public JsonDeserializer<?> findDefaultDeserializer(DeserializationContext ctxt,
17851789
}
17861790
return new UntypedObjectDeserializer(lt, mt);
17871791
}
1792+
// String and equivalents
17881793
if (rawType == CLASS_STRING || rawType == CLASS_CHAR_SEQUENCE) {
17891794
return StringDeserializer.instance;
17901795
}

src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializer.java

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.fasterxml.jackson.databind.deser.std;
22

33
import java.io.IOException;
4+
import java.io.Serializable;
45
import java.lang.reflect.Constructor;
56
import java.lang.reflect.Method;
67
import java.net.MalformedURLException;
@@ -72,9 +73,13 @@ public static StdKeyDeserializer forType(Class<?> raw)
7273
int kind;
7374

7475
// first common types:
75-
if (raw == String.class || raw == Object.class || raw == CharSequence.class) {
76+
if (raw == String.class || raw == Object.class
77+
|| raw == CharSequence.class
78+
// see [databind#2115]:
79+
|| raw == Serializable.class) {
7680
return StringKD.forType(raw);
77-
} else if (raw == UUID.class) {
81+
}
82+
if (raw == UUID.class) {
7883
kind = TYPE_UUID;
7984
} else if (raw == Integer.class) {
8085
kind = TYPE_INT;

src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializers.java

+1-3
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,7 @@ public static KeyDeserializer constructDelegatingKeyDeserializer(Deserialization
4848
public static KeyDeserializer findStringBasedKeyDeserializer(DeserializationConfig config,
4949
JavaType type)
5050
{
51-
/* We don't need full deserialization information, just need to
52-
* know creators.
53-
*/
51+
// We don't need full deserialization information, just need to know creators.
5452
BeanDescription beanDesc = config.introspect(type);
5553
// Ok, so: can we find T(String) constructor?
5654
Constructor<?> ctor = beanDesc.findSingleArgConstructor(String.class);

src/test/java/com/fasterxml/jackson/databind/deser/jdk/UntypedDeserializationTest.java

+27
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import com.fasterxml.jackson.annotation.JsonTypeInfo;
1010
import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
1111
import com.fasterxml.jackson.core.*;
12+
import com.fasterxml.jackson.core.type.TypeReference;
1213
import com.fasterxml.jackson.databind.*;
1314
import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
1415
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
@@ -114,6 +115,11 @@ static class WrappedUntyped1460 {
114115
public Object value;
115116
}
116117

118+
// [databind#2115]
119+
static class SerContainer {
120+
public java.io.Serializable value;
121+
}
122+
117123
/*
118124
/**********************************************************
119125
/* Test methods
@@ -383,4 +389,25 @@ public void testUntypedIntAsLong() throws Exception
383389
.readValue(JSON);
384390
assertEquals(Long.valueOf(3), w.value);
385391
}
392+
393+
// [databind#2115]: Consider `java.io.Serializable` as sort of alias of `java.lang.Object`
394+
// since all natural target types do implement `Serializable` so assignment works
395+
public void testSerializable() throws Exception
396+
{
397+
final String JSON1 = aposToQuotes("{ 'value' : 123 }");
398+
SerContainer cont = MAPPER.readValue(JSON1, SerContainer.class);
399+
assertEquals(Integer.valueOf(123), cont.value);
400+
401+
cont = MAPPER.readValue(aposToQuotes("{ 'value' : true }"), SerContainer.class);
402+
assertEquals(Boolean.TRUE, cont.value);
403+
404+
// But also via Map value, even key
405+
Map<?,?> map = MAPPER.readValue(JSON1, new TypeReference<Map<String, Serializable>>() { });
406+
assertEquals(1, map.size());
407+
assertEquals(Integer.valueOf(123), map.get("value"));
408+
409+
map = MAPPER.readValue(JSON1, new TypeReference<Map<Serializable, Object>>() { });
410+
assertEquals(1, map.size());
411+
assertEquals("value", map.keySet().iterator().next());
412+
}
386413
}

src/test/java/com/fasterxml/jackson/databind/module/TestAbstractTypes.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ public String getValue() {
7777
return value;
7878
}
7979
}
80-
80+
8181
/*
8282
/**********************************************************************
8383
/* Test methods
@@ -157,7 +157,7 @@ public void testInterfaceDefaulting() throws Exception
157157
}
158158

159159
// [databind#2019]: mappings from multiple modules
160-
public static void testAbstractMappingsFromTwoModules() throws Exception
160+
public void testAbstractMappingsFromTwoModules() throws Exception
161161
{
162162
ObjectMapper mapper = newObjectMapper();
163163
SimpleModule module1 = new SimpleModule("module1");

0 commit comments

Comments
 (0)