I have this class:
public class MyLocalApplicationClass {
private String name
private LocalDateTime creationDate;
private String createdBy;
}
And in a response that I receive from a rest service I get this object (as a json):
public class MyRemoteApplicationClass {
private String name
private Date creationDate;
private String createdBy;
}
So when I send the request I get the value (json) of creationDate from MyRemoteApplicationClass like this:
{
“name”:”anything”,
"creation_date": 1666190973000,
"created_by": “anyone”
}
So I was wondering if it is possible to receive this as a LocalDateTime or I should receive it as a Date and then cast it to LocalDateTime (think this is my best option)?
Because I am trying to receive it as a LocalDateTime but it throws this error:
"raw timestamp (1656015404000) not allowed for `java.time.LocalDateTime`: need additional information such as an offset or time-zone (see class Javadocs)"
Also I tried to receive it as LocalDate only, but it throws this error (which I already added the dependency of jsr310 and also added the serializer and deserializer with this annotations @JsonSerialize(using = LocalDateSerializer.class) @JsonDeserialize(using = LocalDateDeserializer.class) so I think the real problem is the warning) and warning:
Java 8 date/time type `java.time.DateTimeException` not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling (through reference chain: com.fasterxml.jackson.databind.JsonMappingException["cause"])
WARN -- com.fasterxml.jackson.databind.JsonMappingException: Invalid value for EpochDay (valid values -365243219162 - 365241780471): 1656015404000
CodePudding user response:
There are several possible solutions:
- You can declare all-args constructor in your
MyLocalApplicationClassand annotate each argument with@JsonProperty. The and the contranctior parametercreationDateshould be received aslong. It would be parsed from epoch millisecond toLocalDateTimemanually.
Here's it might look like:
public class MyLocalApplicationClass {
private String name;
private LocalDateTime creationDate;
private String createdBy;
public MyLocalApplicationClass(@JsonProperty("name") String name,
@JsonProperty("creationDate") long creationDate,
@JsonProperty("createdBy") String createdBy) {
this.name = name;
this.createdBy = createdBy;
this.creationDate = Instant
.ofEpochMilli(creationDate)
.atZone(ZoneOffset.UTC)
.toLocalDateTime();
}
}
- Another option would be to change the type of
creationDateproperty toInstant. To make working we would need to configureObjectMapperby registeringJavaTimeModulemodule and instructing mapper about the precision of the timestamp, namely setting deserialization propertyDeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDSto false. For that we need to placeJackson2ObjectMapperBuilderandObjectMapperas Beans into the Spring's Context.
@Configuration
public class JsonConfig {
@Bean
public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() {
return new Jackson2ObjectMapperBuilder();
}
@Bean
public ObjectMapper objectMapper() {
return jackson2ObjectMapperBuilder()
.build()
.registerModule(new JavaTimeModule())
.configure(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS, false);
}
}
That would allow deserializing MyLocalApplicationClass without making use of data-binding annotations (but only if creationDate would be declared as of type Instant):
public class MyLocalApplicationClass {
private String name;
private Instant creationDate;
private String createdBy;
// getter, setters, etc.
}
- Lastly, we can implement a custom
Deserializerand apply it by annotatingcreationDatefield with@JsonDeserializeannotation.
