Jackson can't serialize Object when contained In Map<String, Object>

481 Views Asked by At

When requesting a single com.codahale.metrics.Meter via Jersey-REST-Service, Jackson is doing just fine and serializes the Meter to (formatting done by me)

{
  "count":0,
  "fiveMinuteRate":0.0,
  "fifteenMinuteRate":0.0,
  "oneMinuteRate":0.0,
  "meanRate":0.0
}

When requesting the same Meter contained inside a Map<String, Metric>, Jackson complaines:

No serializer found for class com.codahale.metrics.Meter and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: java.util.HashMap["testMetric"])

I could just make my resource-method return the String that the ObjectMapper is able to create (see below), but I would like to keep my method returning Map<String, Metric>.

Why can't Jackson figure it out on its own? How can I make Jackson realize that it knows how to serialize the Object? How can I check the configuration of the ObjectMapper used by Jersey?

I have verified that the Map is not empty and that the Meter is acutally there.

When I create a vanilla ObjectMapper and serialize the Map

ObjectMapper mapper = new ObjectMapper();
mapper.writeValueAsString( myMetricMap );

it works just fine:

{
  "testMetric":
  {
    "count":0,
    "fiveMinuteRate":0.0,
    "fifteenMinuteRate":0.0,
    "oneMinuteRate":0.0,
    "meanRate":0.0
  }
}

dropwizard-metrics provides a metrics-json-Package that includes Serializers for Metrics and HealthChecks. Unfortunately, due to a dependency mess, I cannot use it.

EDIT: As it was suggested in the comments, I've tried to serialize a Map<String, Meter> - and it worked!

To summarize:

public interface Metric {
  // Empty Marker Interface
}

public class Meter implements Metric {
  ...
}

@Path("/")
@Produces( MediaType.APPLICATION_JSON )
public MetricsResource {
  @GET
  @Path("metric/{metricName}")
  public Metric getMetric( @PathParam String metricName ) {
    // Works!
    return MetricsService.getMetric( metricName );
  }

  @GET
  @Path("metricsAsString")
  public String getMetricsAsString()
  {
    // Works!
    return (new ObjectMapper()).writeValueAsString(
        MetricsService.getMetrics());
  }

  @GET
  @Path("meters")
  public Map<String, Meter> getMeters()
  {
    // Works!
    return MetricsService.getMeters();
  }

  @GET
  @Path("metrics")
  public Map<String, Metric> getMetrics()
  {
    // Fails!
    return metricsService.getMetrics();
}

I suppose that jackson is not determining the concrete Type when implicitly serializing, but is trying to serialize based on the (marker) Interface Metric.

0

There are 0 best solutions below