Парсинг времени с плавающим количеством миллисекунд
Есть ответ api-запроса, который автоматически парсится, выглядит это примерно вот так :
public class Message {
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss[.SSSSSSSSS]X")
private ZonedDateTime createdAt;
@Builder.Default
private String message = RandomUtils.getRuFaker().lorem().paragraph();
private Integer id;
private Integer topicId;}
Дело в том, что в объекте createdAt приходи время с разным количеством миллисекунд. Например :
- 2021-05-19T08:51:16.404030Z
- 2021-05-18T20:06:13.726886244Z
Как распарсить такое чтобы меньше костылей было?
Ответы (2 шт):
Попробуйте так. Нужен будет кастомный Deserializer для поля и все будет хорошо.
public class Message {
@JsonDeserialize(using = ZonedDateTimeDeserializer.class)
private ZonedDateTime createdAt;
@Builder.Default
private String message = RandomUtils.getRuFaker().lorem().paragraph();
private Integer id;
private Integer topicId;
}
Собственно сам
ZonedDateTimeDeserializer.java
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import java.io.IOException;
import java.time.ZonedDateTime;
public class ZonedDateTimeDeserializer extends StdDeserializer<ZonedDateTime> {
private static final long serialVersionUID = 1L;
public ZonedDateTimeDeserializer() {
this(null);
}
public ZonedDateTimeDeserializer(Class<?> vc) {
super(vc);
}
@Override
public ZonedDateTime deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
JsonNode node = jp.getCodec().readTree(jp);
final String date = node.textValue();
return ZonedDateTime.parse(date);
}
}
Можете тут
return ZonedDateTime.parse(date);
парсить строку какую хотите в каком то либо формате.
И проверка
public static void main(String[] args) throws Exception {
String json1 =
"{ \"createdAt\": \"2021-05-19T08:51:16.404030Z\", \"message\": \"test\", \"id\":1,"
+ " \"topicId\": null}";
String json2 =
"{ \"createdAt\": \"2021-05-18T20:06:13.726886244Z\", \"message\": \"test\", \"id\":2,"
+ " \"topicId\": null}";
ObjectMapper mapper = new ObjectMapper();
Message message1 = mapper.readValue(json1, Message.class);
Message message2 = mapper.readValue(json2, Message.class);
System.out.println(message1.getCreatedAt()); //2021-05-19T08:51:16.404030Z
System.out.println(message2.getCreatedAt());//2021-05-18T20:06:13.726886244Z
System.out.println(message1.getCreatedAt().getNano()); // 404030000
System.out.println(message2.getCreatedAt().getNano()); // 726886244
}
Можете указать yyyy-MM-dd'T'HH:mm:ss[.SSSSSSSSS][.SSSSSS]X или yyyy-MM-dd'T'HH:mm:ss.[SSSSSSSSS][SSSSSS]X. Также будет корректно работать и без паттерна. Если у Вас все равно возникает ошибка при использовании указанных выше паттернов, то рекомендую Вам обновить версию Jackson-а.
package com.somepackage;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import lombok.Setter;
import lombok.ToString;
import java.time.ZonedDateTime;
class Main {
@Setter
@ToString
public static class Message {
@JsonFormat(
shape = JsonFormat.Shape.STRING,
pattern = "yyyy-MM-dd'T'HH:mm:ss[.SSSSSSSSS][.SSSSSS]X"
)
private ZonedDateTime createdAt;
}
public static void main(String[] args) throws Exception {
final String json1 =
"{\"createdAt\": \"2021-05-19T08:51:16.404030Z\"}";
final String json2 =
"{\"createdAt\": \"2021-05-18T20:06:13.726886244Z\"}";
final ObjectMapper mapper =
new ObjectMapper()
.registerModule(new JavaTimeModule());
final Message message1 = mapper.readValue(json1, Message.class);
System.out.println(message1);
final Message message2 = mapper.readValue(json2, Message.class);
System.out.println(message2);
}
}
Результат:
Main.Message(createdAt=2021-05-19T08:51:16.404030Z[UTC])
Main.Message(createdAt=2021-05-18T20:06:13.726886244Z[UTC])