title: How to use Jackson custom value serializer for Map<String, Object>?
body: <p>I have a result set from DB in form of <code>Map&lt;String, Object&gt;</code> that I should return as <code>json</code> from a REST-service. Values in the map could be of various types including <code>PGObject</code>, <code>String</code>, <code>Integer</code> and <code>Date</code>.</p>
  
  <p>And I wrote a custom serializer for <code>org.postgresql.util.PGObject</code> class with type "jsonb", which works fine in <code>List&lt;?&gt;</code>, but not in <code>Map&lt;String, Object&gt;</code>.</p>
  
  <pre><code>public class PgObjectSerializer extends JsonSerializer&lt;PGobject&gt;{
  
      @Override
      public void serialize(PGobject pgObject, JsonGenerator gen, SerializerProvider serializers) throws IOException {
          switch (pgObject.getType()) {
              case "json":
              case "jsonb":
                  gen.writeRawValue(pgObject.getValue());
                  break;
              default:
                  gen.writeString(pgObject.getValue());
          }
      }
  }
  </code></pre>
  
  <p>Target PGObject looks like this:</p>
  
  <pre><code>PGObject pgo = new PGObject();
  pgo.setType("jsonb");
  pgo.setValue("[{"id": 6, "name": "Foo"}, {"id": 7, "name": "Bar"}, {"id": 8, "name": "Baz"}]"); map.put("reason", pgo);
  </code></pre>
  
  <p>When Jackson serializes this <code>PGObject</code> value in a <code>Map&lt;String, Object&gt;</code> then I get <code>json</code> value like:</p>
  
  <pre><code>  "reason": {
      "type": "jsonb",
      "value": "[{\"id\": 6, \"name\": \"Foo\"}, {\"id\": 7, \"name\": \"Bar\"}, {\"id\": 8, \"name\": \"Baz\"}]"
    }
  </code></pre>
  
  <p>What I need:</p>
  
  <pre><code>  "reason": [
      {
        "id": 6,
        "name": "Foo"
      },
      {
        "id": 7,
        "name": "Bar"
      },
      {
        "id": 8,
        "name": "Baz"
      },
    ],
  </code></pre>
  
  <p>I've tried adding module to <code>ObjectMapper</code> and custom <code>MapType</code> to <code>ObjectWriter</code> as shown in the answer to <a href="https://stackoverflow.com/questions/6574636/serializing-mapdate-string-with-jackson">Serializing Map&lt;Date, String&gt; with Jackson</a>:</p>
  
  <pre><code>@Service
  @Transactional
  public class MyClass {
      private final ObjectWriter writer;
      private final MyRepo repository;
  
      @Autowired
      public MyClass(MyRepo repository) {
          this.repository = repository;
  
          SimpleModule module = new SimpleModule();
          module.addKeySerializer(PGobject.class, new PgObjectSerializer());
  
          ObjectMapper mapper = new ObjectMapper();
          JavaType myMapType = mapper.getTypeFactory().
                  constructMapType(HashMap.class, String.class, PGobject.class);
          writer = mapper.registerModule(module).writerFor(myMapType);
      }
  
      ...
  
      private String toJsonString(Map&lt;String, Object&gt; map) {
          try {
              return writer.writeValueAsString(map);
          } catch (JsonProcessingException e) {
              throw new RuntimeException(e);
          }
      }
  }
  </code></pre>
  
  <p>but I get serialization error for every non-<code>PGObject</code> object in the map:</p>
  
  <pre><code>[Test worker] ERROR 
  com.fasterxml.jackson.databind.JsonMappingException: object is not an instance of declaring class (through reference chain: java.util.HashMap["end_date"]-&gt;java.lang.String["type"])
      at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:388)
      at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:348)
      at com.fasterxml.jackson.databind.ser.std.StdSerializer.wrapAndThrow(StdSerializer.java:343)
      at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:698)
      at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
      at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeFieldsUsing(MapSerializer.java:736)
      at com.fasterxml.jackson.databind.ser.std.MapSerializer.serialize(MapSerializer.java:534)
      at com.fasterxml.jackson.databind.ser.std.MapSerializer.serialize(MapSerializer.java:30)
      at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:416)
      at com.fasterxml.jackson.databind.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1425)
      at com.fasterxml.jackson.databind.ObjectWriter._configAndWriteValue(ObjectWriter.java:1158)
      at com.fasterxml.jackson.databind.ObjectWriter.writeValueAsString(ObjectWriter.java:1031)
  </code></pre>
  
  <p>How to enable my <code>PGObjectSerializer</code> in Jackson when PGObject is found as a value during serialization of a <code>Map&lt;String, Object&gt;</code>?</p>