1
1
package com .fasterxml .jackson .databind .jsontype .impl ;
2
2
3
3
import java .util .*;
4
+ import java .util .concurrent .ConcurrentHashMap ;
4
5
5
6
import com .fasterxml .jackson .annotation .JsonTypeInfo ;
6
7
import com .fasterxml .jackson .databind .BeanDescription ;
@@ -14,46 +15,55 @@ public class TypeNameIdResolver extends TypeIdResolverBase
14
15
protected final MapperConfig <?> _config ;
15
16
16
17
/**
17
- * Mappings from class name to type id, used for serialization
18
+ * Mappings from class name to type id, used for serialization.
19
+ *<p>
20
+ * Since lazily constructed will require synchronization (either internal
21
+ * by type, or external)
18
22
*/
19
- protected final Map <String , String > _typeToId ;
23
+ protected final ConcurrentHashMap <String , String > _typeToId ;
20
24
21
25
/**
22
- * Mappings from type id to JavaType, used for deserialization
26
+ * Mappings from type id to JavaType, used for deserialization.
27
+ *<p>
28
+ * Eagerly constructed, not modified, can use regular unsynchronized {@link Map}.
23
29
*/
24
30
protected final Map <String , JavaType > _idToType ;
25
31
26
32
protected TypeNameIdResolver (MapperConfig <?> config , JavaType baseType ,
27
- Map <String , String > typeToId , Map <String , JavaType > idToType )
33
+ ConcurrentHashMap <String , String > typeToId ,
34
+ HashMap <String , JavaType > idToType )
28
35
{
29
36
super (baseType , config .getTypeFactory ());
30
37
_config = config ;
31
38
_typeToId = typeToId ;
32
39
_idToType = idToType ;
33
40
}
34
-
41
+
35
42
public static TypeNameIdResolver construct (MapperConfig <?> config , JavaType baseType ,
36
43
Collection <NamedType > subtypes , boolean forSer , boolean forDeser )
37
44
{
38
45
// sanity check
39
46
if (forSer == forDeser ) throw new IllegalArgumentException ();
40
- Map <String , String > typeToId = null ;
41
- Map <String , JavaType > idToType = null ;
47
+
48
+ final ConcurrentHashMap <String , String > typeToId ;
49
+ final HashMap <String , JavaType > idToType ;
42
50
43
51
if (forSer ) {
44
- typeToId = new HashMap <String , String >();
45
- }
46
- if (forDeser ) {
47
- idToType = new HashMap <String , JavaType >();
52
+ // Only need Class-to-id for serialization; but synchronized since may be
53
+ // lazily built (if adding type-id-mappings dynamically)
54
+ typeToId = new ConcurrentHashMap <>();
55
+ idToType = null ;
56
+ } else {
57
+ idToType = new HashMap <>();
48
58
// 14-Apr-2016, tatu: Apparently needed for special case of `defaultImpl`;
49
- // see [databind#1198] for details.
50
- typeToId = new TreeMap <String , String >();
59
+ // see [databind#1198] for details: but essentially we only need room
60
+ // for a single value.
61
+ typeToId = new ConcurrentHashMap <>(4 );
51
62
}
52
63
if (subtypes != null ) {
53
64
for (NamedType t : subtypes ) {
54
- /* no name? Need to figure out default; for now, let's just
55
- * use non-qualified class name
56
- */
65
+ // no name? Need to figure out default; for now, let's just
66
+ // use non-qualified class name
57
67
Class <?> cls = t .getType ();
58
68
String id = t .hasName () ? t .getName () : _defaultTypeId (cls );
59
69
if (forSer ) {
@@ -91,10 +101,7 @@ protected String idFromClass(Class<?> clazz)
91
101
// NOTE: although we may need to let `TypeModifier` change actual type to use
92
102
// for id, we can use original type as key for more efficient lookup:
93
103
final String key = clazz .getName ();
94
- String name ;
95
- synchronized (_typeToId ) {
96
- name = _typeToId .get (key );
97
- }
104
+ String name = _typeToId .get (key );
98
105
99
106
if (name == null ) {
100
107
// 29-Nov-2019, tatu: As per test in `TestTypeModifierNameResolution` somehow
@@ -110,9 +117,7 @@ protected String idFromClass(Class<?> clazz)
110
117
// And if still not found, let's choose default?
111
118
name = _defaultTypeId (cls );
112
119
}
113
- synchronized (_typeToId ) {
114
- _typeToId .put (key , name );
115
- }
120
+ _typeToId .put (key , name );
116
121
}
117
122
return name ;
118
123
}
0 commit comments