自定义杰克逊序列化器不与gson合作

时间:2017-01-31 07:28:48

标签: java json serialization jackson gson

我正在使用Jackson& amp;新泽西州。我为主持的API制作了响应POJO。我为日期字段制作了一个自定义Jackson序列化程序,如下所示。

class A{
    LocalDateTime localDateTime = LocalDateTime.now();

    @JsonSerialize(using = JacksonSerializers.DateSecondsFromEpochUTCSerializer.class)
    public LocalDateTime getLocalDateTime() {
        return localDateTime;
    }

    public void setLocalDateTime(LocalDateTime localDateTime) {
        this.localDateTime = localDateTime;
    }
}

Serializer如下:

public class JacksonSerializers {

@Component
public static class DateSecondsFromEpochUTCSerializer extends JsonSerializer<LocalDateTime> {

    @Override
    public void serialize(LocalDateTime localDateTime, JsonGenerator gen, SerializerProvider provider)
            throws IOException, JsonProcessingException {
        gen.writeNumber(localDateTime.toEpochSecond(ZoneOffset.UTC));
    }

}

上面的代码在调用API并且响应包含epoch格式的日期时工作正常。

但是,当我尝试使用GSON lib创建类的JSON时,上面的序列化不起作用。我得到以下不正确的输出:

System.out.print(new Gson().toJson(new A()));

给出

{"localDateTime":{"date":{"year":2017,"month":1,"day":31},"time":{"hour":12,"minute":55,"second":53,"nano":481000000}}}

但我想要1485847871。基本上,我想在两个流程中的纪元时间序列化LocalDateTime。我现在正尝试使用GSON,但这不是硬核要求。任何实现这两种结果的优雅解决方案都可以。

3 个答案:

答案 0 :(得分:1)

可以创建一个可用于Jackson和GSON的统一序列化程序。有点像这样:

public class DateSecondsFromEpochUTCSerializer
        extends com.fasterxml.jackson.databind.JsonSerializer<LocalDateTime>
        implements com.google.gson.JsonSerializer<LocalDateTime> {

    @Override
    public void serialize(LocalDateTime localDateTime, JsonGenerator gen, SerializerProvider provider) throws IOException {
        gen.writeNumber(convert(localDateTime));
    }

    @Override
    public JsonElement serialize(LocalDateTime ldt, Type type, JsonSerializationContext jsonSerializationContext) {
        return new JsonPrimitive(convert(ldt));
    }

    private long convert(LocalDateTime ldt) {
        return ldt.toEpochSecond(ZoneOffset.UTC);
    }
}

将它安装在您的GSON实例中,如下所示:

Gson gson = new GsonBuilder()
    .registerTypeAdapter(LocalDateTime.class, new DateSecondsFromEpochUTCSerializer())
    .create();
System.out.println(gson.toJson(LocalDateTime.now())); // Epoch

答案 1 :(得分:0)

如果你对Gson仍然没有好处,并且不需要介绍Jackson,因为它是一个完全不同的库,你可以使用自定义的Gson类型适配器:

final class LocalDateTimeTypeAdapter
        extends TypeAdapter<LocalDateTime> {

    private static final TypeAdapter<LocalDateTime> localDateTimeTypeAdapter = new LocalDateTimeTypeAdapter();

    private LocalDateTimeTypeAdapter() {
    }

    static TypeAdapter<LocalDateTime> getLocalDateTimeTypeAdapter() {
        return localDateTimeTypeAdapter;
    }

    @Override
    @SuppressWarnings("resource")
    public void write(final JsonWriter out, final LocalDateTime value)
            throws IOException {
        out.value(value.toEpochSecond(UTC));
    }

    @Override
    public LocalDateTime read(final JsonReader in)
            throws IOException {
        return Instant.ofEpochSecond(in.nextLong()).atZone(UTC).toLocalDateTime();
    }

}

这类似于Gson JsonSerializer / JsonDeserializer对,但它更有效,因为后者需要在内存中构建JSON树,而类型适配器以流方式工作并且可能生成值而不是积累中间状态很多。然后只需配置Gson实例:

final Gson gson = new GsonBuilder()
        .registerTypeAdapter(LocalDateTime.class, getLocalDateTimeTypeAdapter())
        .create();
final String json = gson.toJson(new A());
out.println(json);
final A a = gson.fromJson(json, A.class);
out.println(a.localDateTime);

它会产生类似的东西:

  

{ “localDateTime”:1485871467}
  2017-01-31T14:04:27

用于序列化和反序列化。

答案 2 :(得分:0)

对我有用的解决方案:

new ObjectMapper().writeValueAsString(new A())