Джексон делает два атрибута json из одного атрибута java

У меня есть немного проблемы с комфортом, используя Джексон в API отдыха. Я использую Джексона для сериализации объекта, который имеет атрибуты любого типа в java.time, например:

public class DomainObject{
   public LocalDateTime start;
}

Я могу использовать Джексона, чтобы произвести что-то вроде этого:

{
    start: '2017-12-31 17:35:22'
}

И я могу использовать это, чтобы произвести что-то вроде этого:

{
    start: 102394580192345 //milliseconds
}

Но я хотел бы иметь и миллисекунды для работы с JS, и представление String для пользователей, которые используют rest-api исключительно без js-frontend. (В основном я, для отладки)

Так есть ли способ заставить Джексона произвести следующее?

{
    start: 102394580192345 //milliseconds
    startString: '2017-12-31 17:35:22'
}

2 ответа

Решение

Вы можете написать собственный сериализатор Jackson, который затем должен быть зарегистрирован в приложении. После этого каждый экземпляр этого dataType будет сериализован таким образом. Даже если тип данных для сериализации находится внутри другого типа данных. (так же, как ваш пример)

Примечание. Имейте в виду, что я не пишу это для LocalDateTime, так как я написал это для ZonedDateTime в своем приложении. Для вас не должно быть трудной задачей переписать его в соответствии с вашими потребностями.

public class ZonedDateTimeSerializer extends JsonSerializer<ZonedDateTime>
{

  @Override
  public void serialize( ZonedDateTime value, JsonGenerator gen, SerializerProvider serializers ) throws IOException
  {
    gen.writeStartObject();
    gen.writeFieldName( "timestamp" );
    gen.writeString( Long.toString( value.toInstant().toEpochMilli() ) );
    gen.writeFieldName( "offset" );
    gen.writeString( value.getOffset().toString() );
    gen.writeFieldName( "zone" );
    gen.writeString( value.getZone().toString() );
    gen.writeFieldName( "ts" );
    gen.writeString( StringUtils.convertZonedDateTimeToISO8601String( value ) );
    gen.writeEndObject();
  }

}

Затем он регистрируется для ObjectMapper of Jackson следующим образом:

    objectMapper = new ObjectMapper();
    SimpleModule module = new SimpleModule( "MyModule" );
    module.addSerializer( ZonedDateTime.class, new ZonedDateTimeSerializer() );
    objectMapper.registerModule( module );

В этом процессе я бы предложил создать A Producer ( CDI), который всегда будет возвращать objectMapper с этим сериализатором, добавленным по умолчанию. Но я оставлю эту задачу на ваше усмотрение;)

Простым способом было бы сделать преобразование строк самостоятельно как дополнительное поле JSON:

public class DomainObject {
   private LocalDateTime start;

   @JsonProperty("startString")
   public String formatStartDate() {
     // use a date formatter to format the date as string here
   }
}

Джексон будет сериализовать start как обычно, и вы добавили дополнительное поле JSON startString

Другие вопросы по тегам