1 package com.fasterxml.jackson.databind.ser.std;
2
3 import java.io.IOException;
4 import java.util.Calendar;
5 import java.util.Date;
6
7 import com.fasterxml.jackson.core.*;
8 import com.fasterxml.jackson.databind.*;
9 import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
10 import com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap;
11 import com.fasterxml.jackson.databind.util.ClassUtil;
12 import com.fasterxml.jackson.databind.util.EnumValues;
13
14 @SuppressWarnings("serial")
15 public abstract class StdKeySerializers
16 {
17 @SuppressWarnings("deprecation")
18 protected final static JsonSerializer<Object> DEFAULT_KEY_SERIALIZER = new StdKeySerializer();
19
20 protected final static JsonSerializer<Object> DEFAULT_STRING_SERIALIZER = new StringKeySerializer();
21
22
29 public static JsonSerializer<Object> getStdKeySerializer(SerializationConfig config,
30 Class<?> rawKeyType, boolean useDefault)
31 {
32
33
34
35
36
37
38 if ((rawKeyType == null) || (rawKeyType == Object.class)) {
39 return new Dynamic();
40 }
41 if (rawKeyType == String.class) {
42 return DEFAULT_STRING_SERIALIZER;
43 }
44 if (rawKeyType.isPrimitive()) {
45 rawKeyType = ClassUtil.wrapperType(rawKeyType);
46 }
47 if (rawKeyType == Integer.class) {
48 return new Default(Default.TYPE_INTEGER, rawKeyType);
49 }
50 if (rawKeyType == Long.class) {
51 return new Default(Default.TYPE_LONG, rawKeyType);
52 }
53 if (rawKeyType.isPrimitive() || Number.class.isAssignableFrom(rawKeyType)) {
54
55
56 return new Default(Default.TYPE_TO_STRING, rawKeyType);
57 }
58 if (rawKeyType == Class.class) {
59 return new Default(Default.TYPE_CLASS, rawKeyType);
60 }
61 if (Date.class.isAssignableFrom(rawKeyType)) {
62 return new Default(Default.TYPE_DATE, rawKeyType);
63 }
64 if (Calendar.class.isAssignableFrom(rawKeyType)) {
65 return new Default(Default.TYPE_CALENDAR, rawKeyType);
66 }
67
68 if (rawKeyType == java.util.UUID.class) {
69 return new Default(Default.TYPE_TO_STRING, rawKeyType);
70 }
71 if (rawKeyType == byte[].class) {
72 return new Default(Default.TYPE_BYTE_ARRAY, rawKeyType);
73 }
74 if (useDefault) {
75
76 return new Default(Default.TYPE_TO_STRING, rawKeyType);
77 }
78 return null;
79 }
80
81
87 @SuppressWarnings("unchecked")
88 public static JsonSerializer<Object> getFallbackKeySerializer(SerializationConfig config,
89 Class<?> rawKeyType)
90 {
91 if (rawKeyType != null) {
92
93
94
95
96
97
98 if (rawKeyType == Enum.class) {
99 return new Dynamic();
100 }
101
102
103 if (ClassUtil.isEnumType(rawKeyType)) {
104 return EnumKeySerializer.construct(rawKeyType,
105 EnumValues.constructFromName(config, (Class<Enum<?>>) rawKeyType));
106 }
107 }
108
109 return new Default(Default.TYPE_TO_STRING, rawKeyType);
110 }
111
112
115 @Deprecated
116 public static JsonSerializer<Object> getDefault() {
117 return DEFAULT_KEY_SERIALIZER;
118 }
119
120
125
126
134 public static class Default extends StdSerializer<Object> {
135 final static int TYPE_DATE = 1;
136 final static int TYPE_CALENDAR = 2;
137 final static int TYPE_CLASS = 3;
138 final static int TYPE_ENUM = 4;
139 final static int TYPE_INTEGER = 5;
140 final static int TYPE_LONG = 6;
141 final static int TYPE_BYTE_ARRAY = 7;
142 final static int TYPE_TO_STRING = 8;
143
144 protected final int _typeId;
145
146 public Default(int typeId, Class<?> type) {
147 super(type, false);
148 _typeId = typeId;
149 }
150
151 @Override
152 public void serialize(Object value, JsonGenerator g, SerializerProvider provider) throws IOException {
153 switch (_typeId) {
154 case TYPE_DATE:
155 provider.defaultSerializeDateKey((Date)value, g);
156 break;
157 case TYPE_CALENDAR:
158 provider.defaultSerializeDateKey(((Calendar) value).getTimeInMillis(), g);
159 break;
160 case TYPE_CLASS:
161 g.writeFieldName(((Class<?>)value).getName());
162 break;
163 case TYPE_ENUM:
164 {
165 String key;
166
167 if (provider.isEnabled(SerializationFeature.WRITE_ENUMS_USING_TO_STRING)) {
168 key = value.toString();
169 } else {
170 Enum<?> e = (Enum<?>) value;
171
172 if (provider.isEnabled(SerializationFeature.WRITE_ENUM_KEYS_USING_INDEX)) {
173 key = String.valueOf(e.ordinal());
174 } else {
175 key = e.name();
176 }
177 }
178 g.writeFieldName(key);
179 }
180 break;
181 case TYPE_INTEGER:
182 case TYPE_LONG:
183 g.writeFieldId(((Number) value).longValue());
184 break;
185 case TYPE_BYTE_ARRAY:
186 {
187 String encoded = provider.getConfig().getBase64Variant().encode((byte[]) value);
188 g.writeFieldName(encoded);
189 }
190 break;
191 case TYPE_TO_STRING:
192 default:
193 g.writeFieldName(value.toString());
194 }
195 }
196 }
197
198
202 public static class Dynamic extends StdSerializer<Object>
203 {
204
205 protected transient PropertySerializerMap _dynamicSerializers;
206
207 public Dynamic() {
208 super(String.class, false);
209 _dynamicSerializers = PropertySerializerMap.emptyForProperties();
210 }
211
212 Object readResolve() {
213
214 _dynamicSerializers = PropertySerializerMap.emptyForProperties();
215 return this;
216 }
217
218 @Override
219 public void serialize(Object value, JsonGenerator g, SerializerProvider provider)
220 throws IOException
221 {
222 Class<?> cls = value.getClass();
223 PropertySerializerMap m = _dynamicSerializers;
224 JsonSerializer<Object> ser = m.serializerFor(cls);
225 if (ser == null) {
226 ser = _findAndAddDynamic(m, cls, provider);
227 }
228 ser.serialize(value, g, provider);
229 }
230
231 @Override
232 public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException {
233 visitStringFormat(visitor, typeHint);
234 }
235
236 protected JsonSerializer<Object> _findAndAddDynamic(PropertySerializerMap map,
237 Class<?> type, SerializerProvider provider) throws JsonMappingException
238 {
239
240 if (type == Object.class) {
241
242 JsonSerializer<Object> ser = new Default(Default.TYPE_TO_STRING, type);
243 _dynamicSerializers = map.newWith(type, ser);
244 return ser;
245 }
246 PropertySerializerMap.SerializerAndMapResult result =
247
248 map.findAndAddKeySerializer(type, provider, null);
249
250 if (map != result.map) {
251 _dynamicSerializers = result.map;
252 }
253 return result.serializer;
254 }
255 }
256
257
260 public static class StringKeySerializer extends StdSerializer<Object>
261 {
262 public StringKeySerializer() { super(String.class, false); }
263
264 @Override
265 public void serialize(Object value, JsonGenerator g, SerializerProvider provider) throws IOException {
266 g.writeFieldName((String) value);
267 }
268 }
269
270
275 public static class EnumKeySerializer extends StdSerializer<Object>
276 {
277 protected final EnumValues _values;
278
279 protected EnumKeySerializer(Class<?> enumType, EnumValues values) {
280 super(enumType, false);
281 _values = values;
282 }
283
284 public static EnumKeySerializer construct(Class<?> enumType,
285 EnumValues enumValues)
286 {
287 return new EnumKeySerializer(enumType, enumValues);
288 }
289
290 @Override
291 public void serialize(Object value, JsonGenerator g, SerializerProvider serializers)
292 throws IOException
293 {
294 if (serializers.isEnabled(SerializationFeature.WRITE_ENUMS_USING_TO_STRING)) {
295 g.writeFieldName(value.toString());
296 return;
297 }
298 Enum<?> en = (Enum<?>) value;
299
300 if (serializers.isEnabled(SerializationFeature.WRITE_ENUM_KEYS_USING_INDEX)) {
301 g.writeFieldName(String.valueOf(en.ordinal()));
302 return;
303 }
304 g.writeFieldName(_values.serializedValueFor(en));
305 }
306 }
307 }
308