1 package com.buckosoft.PicMan.service.support;
2
3 import java.io.IOException;
4 import java.lang.reflect.Type;
5 import java.util.*;
6
7 import com.fasterxml.jackson.core.*;
8 import com.fasterxml.jackson.databind.*;
9 import com.fasterxml.jackson.databind.annotation.JacksonStdImpl;
10 import com.fasterxml.jackson.databind.introspect.AnnotatedMember;
11 import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
12 import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
13 import com.fasterxml.jackson.databind.node.ObjectNode;
14 import com.fasterxml.jackson.databind.ser.ContainerSerializer;
15 import com.fasterxml.jackson.databind.ser.ContextualSerializer;
16 import com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap;
17 import com.fasterxml.jackson.databind.type.TypeFactory;
18
19
20
21
22
23
24
25
26 @JacksonStdImpl
27 public class KeyValueMapSerializer extends ContainerSerializer<Map<?, ?>>
28 implements ContextualSerializer, MapLabels {
29 protected final static JavaType UNSPECIFIED_TYPE = TypeFactory
30 .unknownType();
31
32
33
34
35 protected final BeanProperty _property;
36
37
38
39
40 protected final HashSet<String> _ignoredEntries;
41
42
43
44
45
46 protected final boolean _valueTypeIsStatic;
47
48
49
50
51 protected final JavaType _keyType;
52
53
54
55
56 protected final JavaType _valueType;
57
58
59
60
61 protected JsonSerializer<Object> _keySerializer;
62
63
64
65
66 protected final TypeSerializer _keyTypeSerializer;
67
68
69
70
71 protected JsonSerializer<Object> _valueSerializer;
72
73
74
75
76 protected final TypeSerializer _valueTypeSerializer;
77
78
79
80
81
82 protected PropertySerializerMap _dynamicValueSerializers;
83
84
85
86
87
88
89 @SuppressWarnings("unchecked")
90 protected KeyValueMapSerializer(HashSet<String> ignoredEntries,
91 JavaType keyType, JavaType valueType, boolean valueTypeIsStatic,
92 TypeSerializer kts, TypeSerializer vts,
93 JsonSerializer<?> keySerializer, JsonSerializer<?> valueSerializer) {
94 super(Map.class, false);
95 _ignoredEntries = ignoredEntries;
96 _keyType = keyType;
97 _valueType = valueType;
98 _valueTypeIsStatic = valueTypeIsStatic;
99 _valueTypeSerializer = vts;
100 _keyTypeSerializer = kts;
101 _keySerializer = (JsonSerializer<Object>) keySerializer;
102 _valueSerializer = (JsonSerializer<Object>) valueSerializer;
103 _dynamicValueSerializers = PropertySerializerMap.emptyMap();
104 _property = null;
105 }
106
107 @SuppressWarnings("unchecked")
108 protected KeyValueMapSerializer(KeyValueMapSerializer src,
109 BeanProperty property, JsonSerializer<?> keySerializer,
110 JsonSerializer<?> valueSerializer, HashSet<String> ignored) {
111 super(Map.class, false);
112 _ignoredEntries = ignored;
113 _keyType = src._keyType;
114 _valueType = src._valueType;
115 _valueTypeIsStatic = src._valueTypeIsStatic;
116 _valueTypeSerializer = src._valueTypeSerializer;
117 _keySerializer = (JsonSerializer<Object>) keySerializer;
118 _keyTypeSerializer = src._keyTypeSerializer;
119 _valueSerializer = (JsonSerializer<Object>) valueSerializer;
120 _dynamicValueSerializers = src._dynamicValueSerializers;
121 _property = property;
122 }
123
124 protected KeyValueMapSerializer(KeyValueMapSerializer src,
125 TypeSerializer vts) {
126 super(Map.class, false);
127 _ignoredEntries = src._ignoredEntries;
128 _keyType = src._keyType;
129 _valueType = src._valueType;
130 _valueTypeIsStatic = src._valueTypeIsStatic;
131 _valueTypeSerializer = vts;
132 _keySerializer = src._keySerializer;
133 _keyTypeSerializer = src._keyTypeSerializer;
134 _valueSerializer = src._valueSerializer;
135 _dynamicValueSerializers = src._dynamicValueSerializers;
136 _property = src._property;
137 }
138
139 @Override
140 public KeyValueMapSerializer _withValueTypeSerializer(TypeSerializer vts) {
141 return new KeyValueMapSerializer(this, vts);
142 }
143
144 public KeyValueMapSerializer withResolved(BeanProperty property,
145 JsonSerializer<?> keySerializer, JsonSerializer<?> valueSerializer,
146 HashSet<String> ignored) {
147 return new KeyValueMapSerializer(this, property, keySerializer,
148 valueSerializer, ignored);
149 }
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180 public JsonSerializer<?> createContextual(SerializerProvider provider,
181 BeanProperty property) throws JsonMappingException {
182
183
184
185
186
187 JsonSerializer<?> ser = null;
188 JsonSerializer<?> keySer = null;
189
190
191 if (property != null) {
192 AnnotatedMember m = property.getMember();
193 if (m != null) {
194 Object serDef;
195 final AnnotationIntrospector intr = provider
196 .getAnnotationIntrospector();
197 serDef = intr.findKeySerializer(m);
198 if (serDef != null) {
199 keySer = provider.serializerInstance(m, serDef);
200 }
201 serDef = intr.findContentSerializer(m);
202 if (serDef != null) {
203 ser = provider.serializerInstance(m, serDef);
204 }
205 }
206 }
207 if (ser == null) {
208 ser = _valueSerializer;
209 }
210 if (ser == null) {
211
212
213
214 if (_valueTypeIsStatic
215 || hasContentTypeAnnotation(provider, property)) {
216 ser = provider.findValueSerializer(_valueType, property);
217 }
218 } else if (ser instanceof ContextualSerializer) {
219 ser = ((ContextualSerializer) ser).createContextual(provider,
220 property);
221 }
222 if (keySer == null) {
223 keySer = _keySerializer;
224 }
225 if (keySer == null) {
226 keySer = provider.findValueSerializer(_keyType, property);
227 } else if (keySer instanceof ContextualSerializer) {
228 keySer = ((ContextualSerializer) keySer).createContextual(provider,
229 property);
230 }
231 HashSet<String> ignored = this._ignoredEntries;
232 AnnotationIntrospector intr = provider.getAnnotationIntrospector();
233 if (intr != null && property != null) {
234 String[] moreToIgnore = intr.findPropertiesToIgnore(property
235 .getMember());
236 if (moreToIgnore != null) {
237 ignored = (ignored == null) ? new HashSet<String>()
238 : new HashSet<String>(ignored);
239 for (String str : moreToIgnore) {
240 ignored.add(str);
241 }
242 }
243 }
244 return withResolved(property, keySer, ser, ignored);
245 }
246
247
248
249
250
251
252 @Override
253 public JavaType getContentType() {
254 return _valueType;
255 }
256
257 @Override
258 public JsonSerializer<?> getContentSerializer() {
259 return _valueSerializer;
260 }
261
262 @Override
263 public boolean isEmpty(Map<?, ?> value) {
264 return (value == null) || value.isEmpty();
265 }
266
267 @Override
268 public boolean hasSingleElement(Map<?, ?> value) {
269 return (value.size() == 1);
270 }
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286 public JsonSerializer<?> getKeySerializer() {
287 return _keySerializer;
288 }
289
290
291
292
293
294
295
296 @Override
297 public void serialize(Map<?, ?> value, JsonGenerator jgen,
298 SerializerProvider provider) throws IOException,
299 JsonGenerationException {
300 jgen.writeStartArray();
301 if (!value.isEmpty()) {
302 if (provider
303 .isEnabled(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS)) {
304 value = _orderEntries(value);
305 }
306 if (_valueSerializer != null) {
307 serializeFieldsUsing(value, jgen, provider, _valueSerializer);
308 } else {
309 serializeFields(value, jgen, provider);
310 }
311 }
312 jgen.writeEndArray();
313 }
314
315 @Override
316 public void serializeWithType(Map<?, ?> value, JsonGenerator jgen,
317 SerializerProvider provider, TypeSerializer typeSer)
318 throws IOException, JsonGenerationException {
319 typeSer.writeTypePrefixForObject(value, jgen);
320 jgen.writeStartArray();
321 if (!value.isEmpty()) {
322 if (provider
323 .isEnabled(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS)) {
324 value = _orderEntries(value);
325 }
326 if (_valueSerializer != null) {
327 serializeFieldsUsing(value, jgen, provider, _valueSerializer);
328 } else {
329 serializeFields(value, jgen, provider);
330 }
331 }
332 jgen.writeEndArray();
333 typeSer.writeTypeSuffixForObject(value, jgen);
334
335 }
336
337
338
339
340
341
342
343
344
345
346
347 public void serializeFields(Map<?, ?> value, JsonGenerator jgen,
348 SerializerProvider provider) throws IOException,
349 JsonGenerationException {
350
351 if (_valueTypeSerializer != null || _keyTypeSerializer != null) {
352 serializeTypedFields(value, jgen, provider);
353 return;
354 }
355 final JsonSerializer<Object> keySerializer = _keySerializer;
356
357 final HashSet<String> ignored = _ignoredEntries;
358 final boolean skipNulls = !provider
359 .isEnabled(SerializationFeature.WRITE_NULL_MAP_VALUES);
360
361 PropertySerializerMap serializers = _dynamicValueSerializers;
362
363 for (Map.Entry<?, ?> entry : value.entrySet()) {
364 Object valueElem = entry.getValue();
365
366 Object keyElem = entry.getKey();
367
368 jgen.writeStartObject();
369 jgen.writeFieldName(MAP_KEY_NAME);
370
371 if (keyElem == null) {
372 provider.findNullKeySerializer(_keyType, _property).serialize(
373 null, jgen, provider);
374 } else {
375
376 if (skipNulls && valueElem == null)
377 continue;
378
379 if (ignored != null && ignored.contains(keyElem))
380 continue;
381
382 try {
383 keySerializer.serialize(keyElem, jgen, provider);
384 } catch (Exception ex) {
385 Class<?> cc = keyElem.getClass();
386 JsonSerializer<Object> serializer = serializers
387 .serializerFor(cc);
388 if (serializer == null) {
389 if (_keyType.hasGenericTypes()) {
390 serializer = _findAndAddDynamic(serializers,
391 provider.constructSpecializedType(_keyType,
392 cc), provider);
393 } else {
394 serializer = _findAndAddDynamic(serializers, cc,
395 provider);
396 }
397 serializers = _dynamicValueSerializers;
398 }
399 try {
400 serializer.serialize(keyElem, jgen, provider);
401 } catch (Exception e) {
402
403 String keyDesc = "" + keyElem;
404 wrapAndThrow(provider, e, value, keyDesc);
405 }
406 }
407 }
408
409 jgen.writeFieldName(MAP_VALUE_NAME);
410
411
412 if (valueElem == null) {
413 provider.defaultSerializeNull(jgen);
414 } else {
415 Class<?> cc = valueElem.getClass();
416 JsonSerializer<Object> serializer = serializers
417 .serializerFor(cc);
418 if (serializer == null) {
419 if (_valueType.hasGenericTypes()) {
420 serializer = _findAndAddDynamic(serializers,
421 provider.constructSpecializedType(_valueType,
422 cc), provider);
423 } else {
424 serializer = _findAndAddDynamic(serializers, cc,
425 provider);
426 }
427 serializers = _dynamicValueSerializers;
428 }
429 try {
430 serializer.serialize(valueElem, jgen, provider);
431 } catch (Exception e) {
432
433 String keyDesc = "" + keyElem;
434 wrapAndThrow(provider, e, value, keyDesc);
435 }
436 }
437
438 jgen.writeEndObject();
439 }
440 }
441
442
443
444
445
446
447 protected void serializeFieldsUsing(Map<?, ?> value, JsonGenerator jgen,
448 SerializerProvider provider, JsonSerializer<Object> ser)
449 throws IOException, JsonGenerationException {
450 final JsonSerializer<Object> keySerializer = _keySerializer;
451 final HashSet<String> ignored = _ignoredEntries;
452 final TypeSerializer keySer = _keyTypeSerializer;
453 final TypeSerializer typeSer = _valueTypeSerializer;
454 final boolean skipNulls = !provider
455 .isEnabled(SerializationFeature.WRITE_NULL_MAP_VALUES);
456
457 for (Map.Entry<?, ?> entry : value.entrySet()) {
458 Object valueElem = entry.getValue();
459 Object keyElem = entry.getKey();
460
461 jgen.writeStartObject();
462
463 jgen.writeFieldName(MAP_KEY_NAME);
464
465 if (keyElem == null) {
466 provider.findNullKeySerializer(_keyType, _property).serialize(
467 null, jgen, provider);
468 } else {
469
470 if (skipNulls && valueElem == null)
471 continue;
472
473 if (ignored != null && ignored.contains(keyElem))
474 continue;
475
476 try {
477 if (keySer == null) {
478 keySerializer.serialize(keyElem, jgen, provider);
479 } else {
480 keySerializer.serializeWithType(keyElem, jgen,
481 provider, keySer);
482 }
483 } catch (Exception e) {
484
485 String keyDesc = "" + keyElem;
486 wrapAndThrow(provider, e, value, keyDesc);
487 }
488 }
489
490 jgen.writeFieldName(MAP_VALUE_NAME);
491
492 if (valueElem == null) {
493 provider.defaultSerializeNull(jgen);
494 } else {
495 try {
496 if (typeSer == null) {
497 ser.serialize(valueElem, jgen, provider);
498 } else {
499 ser.serializeWithType(valueElem, jgen, provider,
500 typeSer);
501 }
502 } catch (Exception e) {
503
504 String keyDesc = "" + keyElem;
505 wrapAndThrow(provider, e, value, keyDesc);
506 }
507 }
508
509 jgen.writeEndObject();
510 }
511 }
512
513 protected void serializeTypedFields(Map<?, ?> value, JsonGenerator jgen,
514 SerializerProvider provider) throws IOException,
515 JsonGenerationException {
516 final JsonSerializer<Object> keySerializer = _keySerializer;
517 JsonSerializer<Object> prevValueSerializer = null;
518 Class<?> prevValueClass = null;
519 final HashSet<String> ignored = _ignoredEntries;
520 final boolean skipNulls = !provider
521 .isEnabled(SerializationFeature.WRITE_NULL_MAP_VALUES);
522
523 for (Map.Entry<?, ?> entry : value.entrySet()) {
524 Object valueElem = entry.getValue();
525
526 Object keyElem = entry.getKey();
527
528 jgen.writeStartObject();
529 jgen.writeFieldName(MAP_KEY_NAME);
530
531
532 if (keyElem == null) {
533 provider.findNullKeySerializer(_keyType, _property).serialize(
534 null, jgen, provider);
535 } else {
536
537
538
539
540 if (skipNulls && valueElem == null)
541 continue;
542
543 if (ignored != null && ignored.contains(keyElem))
544 continue;
545 keySerializer.serialize(keyElem, jgen, provider);
546 }
547
548 jgen.writeFieldName(MAP_VALUE_NAME);
549
550
551 if (valueElem == null) {
552 provider.defaultSerializeNull(jgen);
553 } else {
554 Class<?> cc = valueElem.getClass();
555 JsonSerializer<Object> currSerializer;
556 if (cc == prevValueClass) {
557 currSerializer = prevValueSerializer;
558 } else {
559 currSerializer = provider
560 .findValueSerializer(cc, _property);
561 prevValueSerializer = currSerializer;
562 prevValueClass = cc;
563 }
564 try {
565 currSerializer.serializeWithType(valueElem, jgen, provider,
566 _valueTypeSerializer);
567 } catch (Exception e) {
568
569 String keyDesc = "" + keyElem;
570 wrapAndThrow(provider, e, value, keyDesc);
571 }
572 }
573
574 jgen.writeEndObject();
575 }
576 }
577
578 @Override
579 public JsonNode getSchema(SerializerProvider provider, Type typeHint) {
580 ObjectNode o = createSchemaNode("object", true);
581
582
583
584
585 return o;
586 }
587
588 @Override
589 public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor,
590 JavaType typeHint) throws JsonMappingException {
591
592 visitor.expectObjectFormat(typeHint);
593 }
594
595
596
597
598
599
600 @SuppressWarnings("deprecation")
601 protected final JsonSerializer<Object> _findAndAddDynamic(
602 PropertySerializerMap map, Class<?> type,
603 SerializerProvider provider) throws JsonMappingException {
604 PropertySerializerMap.SerializerAndMapResult result = map
605 .findAndAddSerializer(type, provider, _property);
606
607 if (map != result.map) {
608 _dynamicValueSerializers = result.map;
609 }
610 return result.serializer;
611 }
612
613 @SuppressWarnings("deprecation")
614 protected final JsonSerializer<Object> _findAndAddDynamic(
615 PropertySerializerMap map, JavaType type,
616 SerializerProvider provider) throws JsonMappingException {
617 PropertySerializerMap.SerializerAndMapResult result = map
618 .findAndAddSerializer(type, provider, _property);
619 if (map != result.map) {
620 _dynamicValueSerializers = result.map;
621 }
622 return result.serializer;
623 }
624
625 protected Map<?, ?> _orderEntries(Map<?, ?> input) {
626
627 if (input instanceof SortedMap<?, ?>) {
628 return input;
629 }
630 return new TreeMap<Object, Object>(input);
631 }
632
633 }