Home > Mobile >  Can I receive a Date attribute from rest response, as a LocalDateTime or LocalDate in my application
Can I receive a Date attribute from rest response, as a LocalDateTime or LocalDate in my application

Time:11-15

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 MyLocalApplicationClass and annotate each argument with @JsonProperty. The and the contranctior parameter creationDate should be received as long. It would be parsed from epoch millisecond to LocalDateTime manually.

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 creationDate property to Instant. To make working we would need to configure ObjectMapper by registering JavaTimeModule module and instructing mapper about the precision of the timestamp, namely setting deserialization property DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS to false. For that we need to place Jackson2ObjectMapperBuilder and ObjectMapper as 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 Deserializer and apply it by annotating creationDate field with @JsonDeserialize annotation.
  • Related