6
6
7
7
import com .fasterxml .jackson .core .*;
8
8
import com .fasterxml .jackson .databind .*;
9
+ import com .fasterxml .jackson .databind .ser .impl .PropertySerializerMap ;
9
10
10
11
@ SuppressWarnings ("serial" )
11
12
public class StdKeySerializers
@@ -30,28 +31,31 @@ public static JsonSerializer<Object> getStdKeySerializer(SerializationConfig con
30
31
// can not be used, since caller has not yet checked for that annotation
31
32
// This is why Enum types are not handled here quite yet
32
33
33
- if (rawKeyType != null ) {
34
- if (rawKeyType == String .class ) {
35
- return DEFAULT_STRING_SERIALIZER ;
36
- }
37
- if (rawKeyType == Object .class || rawKeyType .isPrimitive ()
38
- || Number .class .isAssignableFrom (rawKeyType )) {
39
- return DEFAULT_KEY_SERIALIZER ;
40
- }
41
- if (rawKeyType == Class .class ) {
42
- return new Default (Default .TYPE_CLASS , rawKeyType );
43
- }
44
- if (Date .class .isAssignableFrom (rawKeyType )) {
45
- return new Default (Default .TYPE_DATE , rawKeyType );
46
- }
47
- if (Calendar .class .isAssignableFrom (rawKeyType )) {
48
- return new Default (Default .TYPE_CALENDAR , rawKeyType );
49
- }
50
- // other JDK types we know convert properly with 'toString()'?
51
- if (rawKeyType == java .util .UUID .class ) {
52
- return new Default (Default .TYPE_TO_STRING , rawKeyType );
53
- }
34
+ // [databind#943: Use a dynamic key serializer if we are not given actual
35
+ // type declaration
36
+ if ((rawKeyType == null ) || (rawKeyType == Object .class )) {
37
+ // !!! TODO
38
+ return new Dynamic ();
39
+ }
54
40
41
+ if (rawKeyType == String .class ) {
42
+ return DEFAULT_STRING_SERIALIZER ;
43
+ }
44
+ if (rawKeyType .isPrimitive () || Number .class .isAssignableFrom (rawKeyType )) {
45
+ return DEFAULT_KEY_SERIALIZER ;
46
+ }
47
+ if (rawKeyType == Class .class ) {
48
+ return new Default (Default .TYPE_CLASS , rawKeyType );
49
+ }
50
+ if (Date .class .isAssignableFrom (rawKeyType )) {
51
+ return new Default (Default .TYPE_DATE , rawKeyType );
52
+ }
53
+ if (Calendar .class .isAssignableFrom (rawKeyType )) {
54
+ return new Default (Default .TYPE_CALENDAR , rawKeyType );
55
+ }
56
+ // other JDK types we know convert properly with 'toString()'?
57
+ if (rawKeyType == java .util .UUID .class ) {
58
+ return new Default (Default .TYPE_TO_STRING , rawKeyType );
55
59
}
56
60
return useDefault ? DEFAULT_KEY_SERIALIZER : null ;
57
61
}
@@ -94,6 +98,14 @@ public static JsonSerializer<Object> getDefault() {
94
98
/**********************************************************
95
99
*/
96
100
101
+ /**
102
+ * This is a "chameleon" style multi-type key serializer for simple
103
+ * standard JDK types.
104
+ *<p>
105
+ * TODO: Should (but does not yet) support re-configuring format used for
106
+ * {@link java.util.Date} and {@link java.util.Calendar} key serializers,
107
+ * as well as alternative configuration of Enum key serializers.
108
+ */
97
109
public static class Default extends StdSerializer <Object > {
98
110
final static int TYPE_DATE = 1 ;
99
111
final static int TYPE_CALENDAR = 2 ;
@@ -134,6 +146,55 @@ public void serialize(Object value, JsonGenerator g, SerializerProvider provider
134
146
}
135
147
}
136
148
149
+ /**
150
+ * Key serializer used when key type is not known statically, and actual key
151
+ * serializer needs to be dynamically located.
152
+ */
153
+ public static class Dynamic extends StdSerializer <Object >
154
+ {
155
+ // Important: MUST be transient, to allow serialization of key serializer itself
156
+ protected transient PropertySerializerMap _dynamicSerializers ;
157
+
158
+ public Dynamic () {
159
+ super (String .class , false );
160
+ _dynamicSerializers = PropertySerializerMap .emptyForProperties ();
161
+ }
162
+
163
+ Object readResolve () {
164
+ // Since it's transient, and since JDK serialization by-passes ctor, need this:
165
+ _dynamicSerializers = PropertySerializerMap .emptyForProperties ();
166
+ return this ;
167
+ }
168
+
169
+ @ Override
170
+ public void serialize (Object value , JsonGenerator g , SerializerProvider provider )
171
+ throws IOException {
172
+ Class <?> cls = value .getClass ();
173
+ PropertySerializerMap m = _dynamicSerializers ;
174
+ JsonSerializer <Object > ser = m .serializerFor (cls );
175
+ if (ser == null ) {
176
+ ser = _findAndAddDynamic (m , cls , provider );
177
+ }
178
+ ser .serialize (value , g , provider );
179
+ }
180
+
181
+ protected JsonSerializer <Object > _findAndAddDynamic (PropertySerializerMap map ,
182
+ Class <?> type , SerializerProvider provider ) throws JsonMappingException
183
+ {
184
+ PropertySerializerMap .SerializerAndMapResult result =
185
+ // null -> for now we won't keep ref or pass BeanProperty; could change
186
+ map .findAndAddKeySerializer (type , provider , null );
187
+ // did we get a new map of serializers? If so, start using it
188
+ if (map != result .map ) {
189
+ _dynamicSerializers = result .map ;
190
+ }
191
+ return result .serializer ;
192
+ }
193
+ }
194
+
195
+ /**
196
+ * Simple and fast key serializer when keys are Strings.
197
+ */
137
198
public static class StringKeySerializer extends StdSerializer <Object >
138
199
{
139
200
public StringKeySerializer () { super (String .class , false ); }
0 commit comments