2017-01-31 11 views
0

Я делаю веб-приложение, используя Джексон & Джерси. Я сделал Response POJO для хостов API. Я создал пользовательский сериализатор Jackson для поля даты, как показано ниже.custom jackson serializer не работает с gson

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, называется и ответ содержит дату в формате эпохи.

Однако приведенная выше сериализация не работает, когда я пытаюсь создать JSON класса с использованием GSON lib. Я получаю ниже неправильный вывод:

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

Не может ли вопрос в основном сводиться к «как мне сериализовать формат LocalDateTime в формате эпохи с помощью GSON?»? Почему часть Джексона, которая, по-видимому, работает по назначению, даже часть вопроса? – Henrik

+0

Потому что это не то, что я намерен спросить. Я уже могу разобрать LocalDateTime на формат epoch в Джерси, используя Джексона. Теперь я использую то же POJO для какой-то другой задачи, и на этот раз я сериализую POJO в JSON, используя GSON, и этот метод не дает желаемого результата, аналогичного тому, что производит Джексон. Я хотел найти общее решение обеих проблем, потому что обе вещи должны работать одновременно. –

+0

ObjectMapper (Jackson) решил обе проблемы. Последняя часть имела предварительное условие к ней, то есть более ранняя сериализация с использованием Джексона не может измениться, но последняя может –

ответ

-1

Найденное решение: new ObjectMapper().writeValueAsString(new A()) работает.

+2

Может быть, я этого не понимаю, но теперь вы больше не используете GSON ... Просто Джексон. –

+0

Да, вы правы. В принципе, я хотел сделать то и другое. GSON не требовал хардкора. –

+2

В этом случае вы должны удалить свой собственный ответ (или, по крайней мере, отредактировать его), потому что это не подходящий ответ. Это очень интересный вопрос, и, возможно, у кого-то есть решение? –

1

Возможно создание унифицированного сериализатора, который вы можете использовать как для Джексона, так и для 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 
0

Если вы все еще хорошо с Gson, и не требуют Джексона быть введены, так как это полностью другая библиотека, вы можете использовать пользовательский тип 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

как для сериализации, так и для десериализации.

 Смежные вопросы

  • Нет связанных вопросов^_^