杰克逊使一个 java 属性的两个 json 属性

jackson make two json attributes of one java attribute

我在休息时使用 jackson 有点不舒服 api。 我正在使用 jackson 序列化具有 java.time 中任何类型属性的对象,例如:

public class DomainObject{
   public LocalDateTime start;
}

我可以使用 jackson 来产生这样的东西:

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

我可以用它来制作这样的东西:

{
    start: 102394580192345 //milliseconds
}

但我想要两者兼有,在 JS 中使用的毫秒数和使用 rest-api 的用户的字符串表示完全没有 js 前端。 (主要是我,用于调试)

那么有什么方法可以让杰克逊产生以下结果吗?

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

您可以编写一个自定义的 Jackson Serializer,然后必须在应用程序中注册它。之后,该数据类型的每次出现都将以这种方式序列化。即使要序列化的数据类型在另一个数据类型中。 (就像你的例子)

注意:请原谅我不要为 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();
  }

}

然后像这样注册到Jackson的ObjectMapper:

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

在此过程中,我建议创建一个 Producer ( CDI ),它将始终 return 一个默认添加此序列化程序的 objectMapper。但我会把这个任务留给你去研究;)

一种简单的方法是自己将字符串转换为额外的 JSON 字段:

public class DomainObject {
   private LocalDateTime start;

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

Jackson 将照常序列化 start,并且您添加了一个额外的 JSON 字段 startString