Coverage Report - com.buckosoft.PicMan.service.support.KeyValueMapSerializer
 
Classes in this File Line Coverage Branch Coverage Complexity
KeyValueMapSerializer
0%
0/251
0%
0/124
4.095
 
 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  
  * Standard serializer implementation for serializing {link java.util.Map}
 21  
  * types.
 22  
  * <p>
 23  
  * Note: about the only configurable setting currently is ability to filter out
 24  
  * entries with specified names.
 25  
  */
 26  0
 @JacksonStdImpl
 27  
 public class KeyValueMapSerializer extends ContainerSerializer<Map<?, ?>>
 28  
                 implements ContextualSerializer, MapLabels {
 29  0
         protected final static JavaType UNSPECIFIED_TYPE = TypeFactory
 30  0
                         .unknownType();
 31  
 
 32  
         /**
 33  
          * Map-valued property being serialized with this instance
 34  
          */
 35  
         protected final BeanProperty _property;
 36  
 
 37  
         /**
 38  
          * Set of entries to omit during serialization, if any
 39  
          */
 40  
         protected final HashSet<String> _ignoredEntries;
 41  
 
 42  
         /**
 43  
          * Whether static types should be used for serialization of values or not
 44  
          * (if not, dynamic runtime type is used)
 45  
          */
 46  
         protected final boolean _valueTypeIsStatic;
 47  
 
 48  
         /**
 49  
          * Declared type of keys
 50  
          */
 51  
         protected final JavaType _keyType;
 52  
 
 53  
         /**
 54  
          * Declared type of contained values
 55  
          */
 56  
         protected final JavaType _valueType;
 57  
 
 58  
         /**
 59  
          * Key serializer to use, if it can be statically determined
 60  
          */
 61  
         protected JsonSerializer<Object> _keySerializer;
 62  
 
 63  
         /**
 64  
          * Type identifier serializer used for keys, if any.
 65  
          */
 66  
         protected final TypeSerializer _keyTypeSerializer;
 67  
 
 68  
         /**
 69  
          * Value serializer to use, if it can be statically determined
 70  
          */
 71  
         protected JsonSerializer<Object> _valueSerializer;
 72  
 
 73  
         /**
 74  
          * Type identifier serializer used for values, if any.
 75  
          */
 76  
         protected final TypeSerializer _valueTypeSerializer;
 77  
 
 78  
         /**
 79  
          * If value type can not be statically determined, mapping from runtime
 80  
          * value types to serializers are stored in this object.
 81  
          */
 82  
         protected PropertySerializerMap _dynamicValueSerializers;
 83  
 
 84  
         /*
 85  
          * /********************************************************** /* Life-cycle
 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  0
                 super(Map.class, false);
 95  0
                 _ignoredEntries = ignoredEntries;
 96  0
                 _keyType = keyType;
 97  0
                 _valueType = valueType;
 98  0
                 _valueTypeIsStatic = valueTypeIsStatic;
 99  0
                 _valueTypeSerializer = vts;
 100  0
                 _keyTypeSerializer = kts;
 101  0
                 _keySerializer = (JsonSerializer<Object>) keySerializer;
 102  0
                 _valueSerializer = (JsonSerializer<Object>) valueSerializer;
 103  0
                 _dynamicValueSerializers = PropertySerializerMap.emptyMap();
 104  0
                 _property = null;
 105  0
         }
 106  
 
 107  
         @SuppressWarnings("unchecked")
 108  
         protected KeyValueMapSerializer(KeyValueMapSerializer src,
 109  
                         BeanProperty property, JsonSerializer<?> keySerializer,
 110  
                         JsonSerializer<?> valueSerializer, HashSet<String> ignored) {
 111  0
                 super(Map.class, false);
 112  0
                 _ignoredEntries = ignored;
 113  0
                 _keyType = src._keyType;
 114  0
                 _valueType = src._valueType;
 115  0
                 _valueTypeIsStatic = src._valueTypeIsStatic;
 116  0
                 _valueTypeSerializer = src._valueTypeSerializer;
 117  0
                 _keySerializer = (JsonSerializer<Object>) keySerializer;
 118  0
                 _keyTypeSerializer = src._keyTypeSerializer;
 119  0
                 _valueSerializer = (JsonSerializer<Object>) valueSerializer;
 120  0
                 _dynamicValueSerializers = src._dynamicValueSerializers;
 121  0
                 _property = property;
 122  0
         }
 123  
 
 124  
         protected KeyValueMapSerializer(KeyValueMapSerializer src,
 125  
                         TypeSerializer vts) {
 126  0
                 super(Map.class, false);
 127  0
                 _ignoredEntries = src._ignoredEntries;
 128  0
                 _keyType = src._keyType;
 129  0
                 _valueType = src._valueType;
 130  0
                 _valueTypeIsStatic = src._valueTypeIsStatic;
 131  0
                 _valueTypeSerializer = vts;
 132  0
                 _keySerializer = src._keySerializer;
 133  0
                 _keyTypeSerializer = src._keyTypeSerializer;
 134  0
                 _valueSerializer = src._valueSerializer;
 135  0
                 _dynamicValueSerializers = src._dynamicValueSerializers;
 136  0
                 _property = src._property;
 137  0
         }
 138  
 
 139  
         @Override
 140  
         public KeyValueMapSerializer _withValueTypeSerializer(TypeSerializer vts) {
 141  0
                 return new KeyValueMapSerializer(this, vts);
 142  
         }
 143  
 
 144  
         public KeyValueMapSerializer withResolved(BeanProperty property,
 145  
                         JsonSerializer<?> keySerializer, JsonSerializer<?> valueSerializer,
 146  
                         HashSet<String> ignored) {
 147  0
                 return new KeyValueMapSerializer(this, property, keySerializer,
 148  
                                 valueSerializer, ignored);
 149  
         }
 150  
 
 151  
         /*
 152  
          * public static KeyValueMapSerializer construct(String[] ignoredList,
 153  
          * JavaType mapType, boolean staticValueType, TypeSerializer vts,
 154  
          * JsonSerializer<Object> keySerializer, JsonSerializer<Object>
 155  
          * valueSerializer) { HashSet<String> ignoredEntries = toSet(ignoredList);
 156  
          * JavaType keyType, valueType;
 157  
          * 
 158  
          * if (mapType == null) { keyType = valueType = UNSPECIFIED_TYPE; } else {
 159  
          * keyType = mapType.getKeyType(); valueType = mapType.getContentType(); }
 160  
          * // If value type is final, it's same as forcing static value typing: if
 161  
          * (!staticValueType) { staticValueType = (valueType != null &&
 162  
          * valueType.isFinal()); } return new KeyValueMapSerializer(ignoredEntries,
 163  
          * keyType, valueType, staticValueType, vts, keySerializer,
 164  
          * valueSerializer); }
 165  
          * 
 166  
          * 
 167  
          * private static HashSet<String> toSet(String[] ignoredEntries) { if
 168  
          * (ignoredEntries == null || ignoredEntries.length == 0) { return null; }
 169  
          * HashSet<String> result = new HashSet<String>(ignoredEntries.length); for
 170  
          * (String prop : ignoredEntries) { result.add(prop); } return result; }
 171  
          */
 172  
 
 173  
         /*
 174  
          * /********************************************************** /*
 175  
          * Post-processing (contextualization)
 176  
          * /**********************************************************
 177  
          */
 178  
 
 179  
         // @Override
 180  
         public JsonSerializer<?> createContextual(SerializerProvider provider,
 181  
                         BeanProperty property) throws JsonMappingException {
 182  
                 /*
 183  
                  * 29-Sep-2012, tatu: Actually, we need to do much more contextual
 184  
                  * checking here since we finally know for sure the property, and it may
 185  
                  * have overrides
 186  
                  */
 187  0
                 JsonSerializer<?> ser = null;
 188  0
                 JsonSerializer<?> keySer = null;
 189  
 
 190  
                 // First: if we have a property, may have property-annotation overrides
 191  0
                 if (property != null) {
 192  0
                         AnnotatedMember m = property.getMember();
 193  0
                         if (m != null) {
 194  
                                 Object serDef;
 195  0
                                 final AnnotationIntrospector intr = provider
 196  0
                                                 .getAnnotationIntrospector();
 197  0
                                 serDef = intr.findKeySerializer(m);
 198  0
                                 if (serDef != null) {
 199  0
                                         keySer = provider.serializerInstance(m, serDef);
 200  
                                 }
 201  0
                                 serDef = intr.findContentSerializer(m);
 202  0
                                 if (serDef != null) {
 203  0
                                         ser = provider.serializerInstance(m, serDef);
 204  
                                 }
 205  
                         }
 206  
                 }
 207  0
                 if (ser == null) {
 208  0
                         ser = _valueSerializer;
 209  
                 }
 210  0
                 if (ser == null) {
 211  
                         // 30-Sep-2012, tatu: One more thing -- if explicit content type is
 212  
                         // annotated,
 213  
                         // we can consider it a static case as well.
 214  0
                         if (_valueTypeIsStatic
 215  0
                                         || hasContentTypeAnnotation(provider, property)) {
 216  0
                                 ser = provider.findValueSerializer(_valueType, property);
 217  
                         }
 218  0
                 } else if (ser instanceof ContextualSerializer) {
 219  0
                         ser = ((ContextualSerializer) ser).createContextual(provider,
 220  
                                         property);
 221  
                 }
 222  0
                 if (keySer == null) {
 223  0
                         keySer = _keySerializer;
 224  
                 }
 225  0
                 if (keySer == null) {
 226  0
                         keySer = provider.findValueSerializer(_keyType, property);
 227  0
                 } else if (keySer instanceof ContextualSerializer) {
 228  0
                         keySer = ((ContextualSerializer) keySer).createContextual(provider,
 229  
                                         property);
 230  
                 }
 231  0
                 HashSet<String> ignored = this._ignoredEntries;
 232  0
                 AnnotationIntrospector intr = provider.getAnnotationIntrospector();
 233  0
                 if (intr != null && property != null) {
 234  0
                         String[] moreToIgnore = intr.findPropertiesToIgnore(property
 235  0
                                         .getMember());
 236  0
                         if (moreToIgnore != null) {
 237  0
                                 ignored = (ignored == null) ? new HashSet<String>()
 238  
                                                 : new HashSet<String>(ignored);
 239  0
                                 for (String str : moreToIgnore) {
 240  0
                                         ignored.add(str);
 241  
                                 }
 242  
                         }
 243  
                 }
 244  0
                 return withResolved(property, keySer, ser, ignored);
 245  
         }
 246  
 
 247  
         /*
 248  
          * /********************************************************** /* Accessors
 249  
          * /**********************************************************
 250  
          */
 251  
 
 252  
         @Override
 253  
         public JavaType getContentType() {
 254  0
                 return _valueType;
 255  
         }
 256  
 
 257  
         @Override
 258  
         public JsonSerializer<?> getContentSerializer() {
 259  0
                 return _valueSerializer;
 260  
         }
 261  
 
 262  
         @Override
 263  
         public boolean isEmpty(Map<?, ?> value) {
 264  0
                 return (value == null) || value.isEmpty();
 265  
         }
 266  
 
 267  
         @Override
 268  
         public boolean hasSingleElement(Map<?, ?> value) {
 269  0
                 return (value.size() == 1);
 270  
         }
 271  
 
 272  
         /*
 273  
          * /********************************************************** /* Extended
 274  
          * API /**********************************************************
 275  
          */
 276  
 
 277  
         /**
 278  
          * Accessor for currently assigned key serializer. Note that this may return
 279  
          * null during construction of <code>MapSerializer</code>: depedencies are
 280  
          * resolved during {@link #createContextual} method (which can be overridden
 281  
          * by custom implementations), but for some dynamic types, it is possible
 282  
          * that serializer is only resolved during actual serialization.
 283  
          * 
 284  
          * @since 2.0
 285  
          */
 286  
         public JsonSerializer<?> getKeySerializer() {
 287  0
                 return _keySerializer;
 288  
         }
 289  
 
 290  
         /*
 291  
          * /********************************************************** /*
 292  
          * JsonSerializer implementation
 293  
          * /**********************************************************
 294  
          */
 295  
 
 296  
         @Override
 297  
         public void serialize(Map<?, ?> value, JsonGenerator jgen,
 298  
                         SerializerProvider provider) throws IOException,
 299  
                         JsonGenerationException {
 300  0
                 jgen.writeStartArray();
 301  0
                 if (!value.isEmpty()) {
 302  0
                         if (provider
 303  0
                                         .isEnabled(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS)) {
 304  0
                                 value = _orderEntries(value);
 305  
                         }
 306  0
                         if (_valueSerializer != null) {
 307  0
                                 serializeFieldsUsing(value, jgen, provider, _valueSerializer);
 308  
                         } else {
 309  0
                                 serializeFields(value, jgen, provider);
 310  
                         }
 311  
                 }
 312  0
                 jgen.writeEndArray();
 313  0
         }
 314  
 
 315  
         @Override
 316  
         public void serializeWithType(Map<?, ?> value, JsonGenerator jgen,
 317  
                         SerializerProvider provider, TypeSerializer typeSer)
 318  
                         throws IOException, JsonGenerationException {
 319  0
                 typeSer.writeTypePrefixForObject(value, jgen);
 320  0
                 jgen.writeStartArray();
 321  0
                 if (!value.isEmpty()) {
 322  0
                         if (provider
 323  0
                                         .isEnabled(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS)) {
 324  0
                                 value = _orderEntries(value);
 325  
                         }
 326  0
                         if (_valueSerializer != null) {
 327  0
                                 serializeFieldsUsing(value, jgen, provider, _valueSerializer);
 328  
                         } else {
 329  0
                                 serializeFields(value, jgen, provider);
 330  
                         }
 331  
                 }
 332  0
                 jgen.writeEndArray();
 333  0
                 typeSer.writeTypeSuffixForObject(value, jgen);
 334  
                 
 335  0
         }
 336  
 
 337  
         /*
 338  
          * /********************************************************** /*
 339  
          * JsonSerializer implementation
 340  
          * /**********************************************************
 341  
          */
 342  
 
 343  
         /**
 344  
          * Method called to serialize fields, when the value type is not statically
 345  
          * known.
 346  
          */
 347  
         public void serializeFields(Map<?, ?> value, JsonGenerator jgen,
 348  
                         SerializerProvider provider) throws IOException,
 349  
                         JsonGenerationException {
 350  
                 // If value type needs polymorphic type handling, some more work needed:
 351  0
                 if (_valueTypeSerializer != null || _keyTypeSerializer != null) {
 352  0
                         serializeTypedFields(value, jgen, provider);
 353  0
                         return;
 354  
                 }
 355  0
                 final JsonSerializer<Object> keySerializer = _keySerializer;
 356  
 
 357  0
                 final HashSet<String> ignored = _ignoredEntries;
 358  0
                 final boolean skipNulls = !provider
 359  0
                                 .isEnabled(SerializationFeature.WRITE_NULL_MAP_VALUES);
 360  
 
 361  0
                 PropertySerializerMap serializers = _dynamicValueSerializers;
 362  
 
 363  0
                 for (Map.Entry<?, ?> entry : value.entrySet()) {
 364  0
                         Object valueElem = entry.getValue();
 365  
                         // First, serialize key
 366  0
                         Object keyElem = entry.getKey();
 367  
                         
 368  0
                         jgen.writeStartObject();
 369  0
                         jgen.writeFieldName(MAP_KEY_NAME);
 370  
                         
 371  0
                         if (keyElem == null) {
 372  0
                                 provider.findNullKeySerializer(_keyType, _property).serialize(
 373  
                                                 null, jgen, provider);
 374  
                         } else {
 375  
                                 // [JACKSON-314] skip entries with null values?
 376  0
                                 if (skipNulls && valueElem == null)
 377  0
                                         continue;
 378  
                                 // One twist: is entry ignorable? If so, skip
 379  0
                                 if (ignored != null && ignored.contains(keyElem))
 380  0
                                         continue;
 381  
 
 382  
                                 try {
 383  0
                                         keySerializer.serialize(keyElem, jgen, provider);
 384  0
                                 } catch (Exception ex) {
 385  0
                                         Class<?> cc = keyElem.getClass();
 386  0
                                         JsonSerializer<Object> serializer = serializers
 387  0
                                                         .serializerFor(cc);
 388  0
                                         if (serializer == null) {
 389  0
                                                 if (_keyType.hasGenericTypes()) {
 390  0
                                                         serializer = _findAndAddDynamic(serializers,
 391  0
                                                                         provider.constructSpecializedType(_keyType,
 392  
                                                                                         cc), provider);
 393  
                                                 } else {
 394  0
                                                         serializer = _findAndAddDynamic(serializers, cc,
 395  
                                                                         provider);
 396  
                                                 }
 397  0
                                                 serializers = _dynamicValueSerializers;
 398  
                                         }
 399  
                                         try {
 400  0
                                                 serializer.serialize(keyElem, jgen, provider);
 401  0
                                         } catch (Exception e) {
 402  
                                                 // [JACKSON-55] Need to add reference information
 403  0
                                                 String keyDesc = "" + keyElem;
 404  0
                                                 wrapAndThrow(provider, e, value, keyDesc);
 405  0
                                         }
 406  0
                                 }
 407  
                         }
 408  
 
 409  0
                         jgen.writeFieldName(MAP_VALUE_NAME);
 410  
                         
 411  
                         // And then value
 412  0
                         if (valueElem == null) {
 413  0
                                 provider.defaultSerializeNull(jgen);
 414  
                         } else {
 415  0
                                 Class<?> cc = valueElem.getClass();
 416  0
                                 JsonSerializer<Object> serializer = serializers
 417  0
                                                 .serializerFor(cc);
 418  0
                                 if (serializer == null) {
 419  0
                                         if (_valueType.hasGenericTypes()) {
 420  0
                                                 serializer = _findAndAddDynamic(serializers,
 421  0
                                                                 provider.constructSpecializedType(_valueType,
 422  
                                                                                 cc), provider);
 423  
                                         } else {
 424  0
                                                 serializer = _findAndAddDynamic(serializers, cc,
 425  
                                                                 provider);
 426  
                                         }
 427  0
                                         serializers = _dynamicValueSerializers;
 428  
                                 }
 429  
                                 try {
 430  0
                                         serializer.serialize(valueElem, jgen, provider);
 431  0
                                 } catch (Exception e) {
 432  
                                         // [JACKSON-55] Need to add reference information
 433  0
                                         String keyDesc = "" + keyElem;
 434  0
                                         wrapAndThrow(provider, e, value, keyDesc);
 435  0
                                 }
 436  
                         }
 437  
                         
 438  0
                         jgen.writeEndObject();
 439  0
                 }
 440  0
         }
 441  
 
 442  
         /**
 443  
          * Method called to serialize fields, when the value type is statically
 444  
          * known, so that value serializer is passed and does not need to be fetched
 445  
          * from provider.
 446  
          */
 447  
         protected void serializeFieldsUsing(Map<?, ?> value, JsonGenerator jgen,
 448  
                         SerializerProvider provider, JsonSerializer<Object> ser)
 449  
                         throws IOException, JsonGenerationException {
 450  0
                 final JsonSerializer<Object> keySerializer = _keySerializer;
 451  0
                 final HashSet<String> ignored = _ignoredEntries;
 452  0
                 final TypeSerializer keySer = _keyTypeSerializer;
 453  0
                 final TypeSerializer typeSer = _valueTypeSerializer;
 454  0
                 final boolean skipNulls = !provider
 455  0
                                 .isEnabled(SerializationFeature.WRITE_NULL_MAP_VALUES);
 456  
 
 457  0
                 for (Map.Entry<?, ?> entry : value.entrySet()) {
 458  0
                         Object valueElem = entry.getValue();
 459  0
                         Object keyElem = entry.getKey();
 460  
 
 461  0
                         jgen.writeStartObject();
 462  
 
 463  0
                         jgen.writeFieldName(MAP_KEY_NAME);
 464  
 
 465  0
                         if (keyElem == null) {
 466  0
                                 provider.findNullKeySerializer(_keyType, _property).serialize(
 467  
                                                 null, jgen, provider);
 468  
                         } else {
 469  
                                 // [JACKSON-314] skip entries with null values?
 470  0
                                 if (skipNulls && valueElem == null)
 471  0
                                         continue;
 472  
                                 // One twist: is entry ignorable? If so, skip
 473  0
                                 if (ignored != null && ignored.contains(keyElem))
 474  0
                                         continue;
 475  
 
 476  
                                 try {
 477  0
                                         if (keySer == null) {
 478  0
                                                 keySerializer.serialize(keyElem, jgen, provider);
 479  
                                         } else {
 480  0
                                                 keySerializer.serializeWithType(keyElem, jgen,
 481  
                                                                 provider, keySer);
 482  
                                         }
 483  0
                                 } catch (Exception e) {
 484  
                                         // [JACKSON-55] Need to add reference information
 485  0
                                         String keyDesc = "" + keyElem;
 486  0
                                         wrapAndThrow(provider, e, value, keyDesc);
 487  0
                                 }
 488  
                         }
 489  
 
 490  0
                         jgen.writeFieldName(MAP_VALUE_NAME);
 491  
 
 492  0
                         if (valueElem == null) {
 493  0
                                 provider.defaultSerializeNull(jgen);
 494  
                         } else {
 495  
                                 try {
 496  0
                                         if (typeSer == null) {
 497  0
                                                 ser.serialize(valueElem, jgen, provider);
 498  
                                         } else {
 499  0
                                                 ser.serializeWithType(valueElem, jgen, provider,
 500  
                                                                 typeSer);
 501  
                                         }
 502  0
                                 } catch (Exception e) {
 503  
                                         // [JACKSON-55] Need to add reference information
 504  0
                                         String keyDesc = "" + keyElem;
 505  0
                                         wrapAndThrow(provider, e, value, keyDesc);
 506  0
                                 }
 507  
                         }
 508  
 
 509  0
                         jgen.writeEndObject();
 510  0
                 }
 511  0
         }
 512  
 
 513  
         protected void serializeTypedFields(Map<?, ?> value, JsonGenerator jgen,
 514  
                         SerializerProvider provider) throws IOException,
 515  
                         JsonGenerationException {
 516  0
                 final JsonSerializer<Object> keySerializer = _keySerializer;
 517  0
                 JsonSerializer<Object> prevValueSerializer = null;
 518  0
                 Class<?> prevValueClass = null;
 519  0
                 final HashSet<String> ignored = _ignoredEntries;
 520  0
                 final boolean skipNulls = !provider
 521  0
                                 .isEnabled(SerializationFeature.WRITE_NULL_MAP_VALUES);
 522  
 
 523  0
                 for (Map.Entry<?, ?> entry : value.entrySet()) {
 524  0
                         Object valueElem = entry.getValue();
 525  
                         // First, serialize key
 526  0
                         Object keyElem = entry.getKey();
 527  
                         
 528  0
                         jgen.writeStartObject();
 529  0
                         jgen.writeFieldName(MAP_KEY_NAME);
 530  
                         
 531  
                         
 532  0
                         if (keyElem == null) {
 533  0
                                 provider.findNullKeySerializer(_keyType, _property).serialize(
 534  
                                                 null, jgen, provider);
 535  
                         } else {
 536  
                                 // TODO: check that case (probably will be [{key}]
 537  
                                 // need to move skipping checks above
 538  
                                 
 539  
                                 // [JACKSON-314] also may need to skip entries with null values
 540  0
                                 if (skipNulls && valueElem == null)
 541  0
                                         continue;
 542  
                                 // One twist: is entry ignorable? If so, skip
 543  0
                                 if (ignored != null && ignored.contains(keyElem))
 544  0
                                         continue;
 545  0
                                 keySerializer.serialize(keyElem, jgen, provider);
 546  
                         }
 547  
 
 548  0
                         jgen.writeFieldName(MAP_VALUE_NAME);
 549  
                         
 550  
                         // And then value
 551  0
                         if (valueElem == null) {
 552  0
                                 provider.defaultSerializeNull(jgen);
 553  
                         } else {
 554  0
                                 Class<?> cc = valueElem.getClass();
 555  
                                 JsonSerializer<Object> currSerializer;
 556  0
                                 if (cc == prevValueClass) {
 557  0
                                         currSerializer = prevValueSerializer;
 558  
                                 } else {
 559  0
                                         currSerializer = provider
 560  0
                                                         .findValueSerializer(cc, _property);
 561  0
                                         prevValueSerializer = currSerializer;
 562  0
                                         prevValueClass = cc;
 563  
                                 }
 564  
                                 try {
 565  0
                                         currSerializer.serializeWithType(valueElem, jgen, provider,
 566  
                                                         _valueTypeSerializer);
 567  0
                                 } catch (Exception e) {
 568  
                                         // [JACKSON-55] Need to add reference information
 569  0
                                         String keyDesc = "" + keyElem;
 570  0
                                         wrapAndThrow(provider, e, value, keyDesc);
 571  0
                                 }
 572  
                         }
 573  
                         
 574  0
                         jgen.writeEndObject();
 575  0
                 }
 576  0
         }
 577  
 
 578  
         @Override
 579  
         public JsonNode getSchema(SerializerProvider provider, Type typeHint) {
 580  0
                 ObjectNode o = createSchemaNode("object", true);
 581  
                 // (ryan) even though it's possible to statically determine the "value"
 582  
                 // type of the map,
 583  
                 // there's no way to statically determine the keys, so the "Entries"
 584  
                 // can't be determined.
 585  0
                 return o;
 586  
         }
 587  
 
 588  
         @Override
 589  
         public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor,
 590  
                         JavaType typeHint) throws JsonMappingException {
 591  
                 // jackphel Aug 17 2012 : this can definitely more more exact.
 592  0
                 visitor.expectObjectFormat(typeHint);
 593  0
         }
 594  
 
 595  
         /*
 596  
          * /********************************************************** /* Internal
 597  
          * helper methods
 598  
          * /**********************************************************
 599  
          */
 600  
         @SuppressWarnings("deprecation")
 601  
         protected final JsonSerializer<Object> _findAndAddDynamic(
 602  
                         PropertySerializerMap map, Class<?> type,
 603  
                         SerializerProvider provider) throws JsonMappingException {
 604  0
                 PropertySerializerMap.SerializerAndMapResult result = map
 605  0
                                 .findAndAddSerializer(type, provider, _property);
 606  
                 // did we get a new map of serializers? If so, start using it
 607  0
                 if (map != result.map) {
 608  0
                         _dynamicValueSerializers = result.map;
 609  
                 }
 610  0
                 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  0
                 PropertySerializerMap.SerializerAndMapResult result = map
 618  0
                                 .findAndAddSerializer(type, provider, _property);
 619  0
                 if (map != result.map) {
 620  0
                         _dynamicValueSerializers = result.map;
 621  
                 }
 622  0
                 return result.serializer;
 623  
         }
 624  
 
 625  
         protected Map<?, ?> _orderEntries(Map<?, ?> input) {
 626  
                 // minor optimization: may already be sorted?
 627  0
                 if (input instanceof SortedMap<?, ?>) {
 628  0
                         return input;
 629  
                 }
 630  0
                 return new TreeMap<Object, Object>(input);
 631  
         }
 632  
 
 633  
 }