Джексон не может сериализовать объект, если он содержится в карте - PullRequest
4 голосов
/ 17 апреля 2019

При запросе одного com.codahale.metrics.Meter через Jersey-REST-Service Джексон работает нормально и сериализует Измеритель (форматирование выполнено мной)

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

При запросе того же Измерителя, содержащегося внутриMap<String, Metric>, Джексон жалуется:

Не найден сериализатор для класса com.codahale.metrics.Meter и не обнаружены свойства для создания BeanSerializer (во избежание исключения отключите SerializationFeature.FAIL_ON_EMPTY_BEANS)) (через цепочку ссылок: java.util.HashMap ["testMetric"])

Я мог бы просто заставить свой метод ресурсов возвращать строку, которую ObjectMapper может создать (см. ниже), но я бы хотелчтобы мой метод возвращал Map<String, Metric>.

Почему Джексон не может понять это самостоятельно?Как я могу заставить Джексона понять, что он знает, как сериализовать Объект?Как я могу проверить конфигурацию ObjectMapper, используемой Джерси?

Я проверил, что Карта не пуста и что Meter находится там точно.

Когда я создаю ваниль ObjectMapper и сериализовать карту

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

, она работает просто отлично:

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

dropwizard-metrics предоставляет пакет metrics-json, который включает в себя сериализаторы для метрик и проверок работоспособности.К сожалению, из-за беспорядка зависимостей я не могу его использовать.

РЕДАКТИРОВАТЬ: Как было предложено в комментариях, я попытался сериализовать Map<String, Meter> - и это сработало!

Подводя итог:

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();
}

Я полагаю, что Джексон не определяет конкретный тип при неявной сериализации, но пытается сериализовать на основе (маркер) интерфейса Metric.

...