I was able to parse a JSON where Instant field is "2019-08-28T15:15:44.183Z"

First of all, ensure you have a dependency. E.g. in build.gradle

implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310'

Then configure ObjectMapper to use this dependency and not (de)serialize Instant as timestamps that it does by default. I setup my ObjectMapper as:

ObjectMapper mapper  = new ObjectMapper()
        .findAndRegisterModules()
        .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
Answer from Manos Nikolaidis on Stack Overflow
🌐
GitHub
github.com › eventuate-foundation › eventuate-common › issues › 50
JSonMapper InvalidDefinitionException on java.time.Instant · Issue #50 · eventuate-foundation/eventuate-common
October 26, 2020 - When the framework is trying to deserialize an object containing a java.time.Instant it throws com.fasterxml.jackson.databind.exc.InvalidDefinitionException. Full stacktrace: java.lang.RuntimeException: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of java.time.Instant(no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator) at [Source: (String)"{"id":1,"status":"PENDING","startTime":{"nano":287862800,"epochSecond":1603712811},"log":"","details":{"id":1,"phase":"CALIBRATION_INIT","erdmD
Author: eventuate-foundation
🌐
Stack Overflow
stackoverflow.com › questions › 64146313 › spring-boot-jersey-client-jackson-cannot-construct-instance-of-java-time-in
Spring Boot - Jersey Client - Jackson Cannot construct instance of `java.time.Instant` - Stack Overflow
October 1, 2020 - com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `java.time.Instant` (no Creators, like default construct, exist): no String-argument constructor/factory method to deserialize from String value ...
🌐
GitHub
github.com › quarkusio › quarkus › issues › 8485
Instance of class Instant creation error - Serialization · Issue #8485 · quarkusio/quarkus
April 8, 2020 - com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `java.time.Instant` (no Creators, like default construct, exist): no String-argument constructor/factory method to deserialize from String value ...
Author: quarkusio
🌐
Elastic
discuss.elastic.co › elastic stack › elasticsearch
Java elasticsearch-java-8.5.1 error on deserialisation of Instant Field - Elasticsearch - Discuss the Elastic Stack
December 7, 2022 - Hi, I have a Spring Boot app (Version 2.7.6) and I'm using the java API client elasticsearch-java-8.5.1. I'm doing a basic query but my object in ES contains an INSTANT value (see POJO below). When I perform the query I get a "com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Java 8 date/time type java.time.Instant not supported by default:" exception.
🌐
Oracle
docs.oracle.com › javase › 8 › docs › api › java › time › Instant.html
Instant (Java Platform SE 8 )
July 21, 2026 - Obtains an instance of Instant from a temporal object. This obtains an instant based on the specified temporal. A TemporalAccessor represents an arbitrary set of date and time information, which this factory converts to an instance of Instant.
🌐
Stack Overflow
stackoverflow.com › questions › linked › 45863678
Hot Linked Questions - Stack Overflow
I am trying to create reservation and I am getting a java.time.LocalDate error like below. com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `java.time....
Top answer
1 of 2
1

Where does this data come from? Is it written by your application?

It seems that the used Jackson mapper does not have the jackson-datatype-jsr310 module registered.

On reading the data tries to find a constructor of Instant that can be used to create an Instant object. But Instant does not have a default constructor and the Mapper should use the Instant.ofEpochSecond(long, long) method. This page pretty declares the problem and shows how the Jackson Mapper is configured.

Storing an instant in this way, as an object with two properties, is not the right way for storing dates in Elasticsearch. You should read the Elasticsearch documentation about how Elastcisearch handles date/time fields. When storing the instant as an object like this, you loose the ability to use Elasticsearch queries with criteria based on a date/time.

Which version of Spring Data Elasticsearch do you use? Because of problems like this, from the upcoming version 4.0 on, Spring Data Elasticsearch will not use the Jackson mapper anymore for entity mapping. The MappingElasticsearchConverter supports the use of the Elasticsearch date format and the java.time classes.

2 of 2
0

Well if I'm not completely wrong, your mapping fails due to the wrong format. The json you get looks like this:

 "createdOn": {
    "nano": 877000000,
    "epochSecond": 1579861613
  },
  "changedOn": {
    "nano": 920000000,
    "epochSecond": 1579861613
  },

That means you have 2 objects 'createdOn' and 'changedOn' with two properties (nano, epochSecond), while you try to map it to one object containing two properties named 'createdOn' and 'changedOn'. You need to modify that, you have e.g. a class called Entry, with two properties (nano, epochSeconds) and then a class with two properties (createdOn, changedOn) of type Entry

Find elsewhere
🌐
GitHub
github.com › spring-projects › spring-boot › issues › 26859
Spring Boot 2.5.0 and InvalidDefinitionException: Java 8 date/time type `java.time.Instant` not supported by default · Issue #26859 · spring-projects/spring-boot
June 11, 2021 - Update: I found the root cause for my issue regarding the actuator/info endpoint. Apparently, there was a place in the code generating a new ObjectMapper bean, and overriding the default. In this case, the ObjectMapper did not load jsr310 and additional java.time classes converters such as Instant.
Top answer
1 of 2
2

Following worked for me in spring-hateoas 1.1.2.RELEASE

private static RestTemplate getRestTemplate() {
    List<HttpMessageConverter<?>> httpMessageConverters = SpringFactoriesLoader.loadFactories(TraversonDefaults.class,
            Traverson.class.getClassLoader()).get(0).getHttpMessageConverters(Collections.singletonList(MediaTypes.HAL_JSON));
    Optional<HttpMessageConverter<?>> first = httpMessageConverters.stream().filter(i -> i instanceof MappingJackson2HttpMessageConverter)
            .findFirst();

    if (first.isPresent()) {
        MappingJackson2HttpMessageConverter httpMessageConverter = (MappingJackson2HttpMessageConverter) first.get();
        httpMessageConverter.getObjectMapper().registerModule(new JavaTimeModule());
    }

    return new RestTemplateBuilder().messageConverters(httpMessageConverters).build();
}

and then using it:

Traverson traverson = new Traverson(URI.create("http://localhost:8080"), MediaTypes.HAL_JSON);
    traverson.setRestOperations(getRestTemplate());
2 of 2
0

After some investigation i found a solution that works for me. The background is that the traverson client registers a MappingJackson2HttpMessageConverter with contains the Jackson2HalModule. To fix the problem i had to register also the JavaTimeModule.

I did the following

RestTemplateBuilder genericBuilder = this.restTemplateBuilder
    .setConnectTimeout(Duration.ofMillis(configuration.getSecurityRestConnectTimeout()))
    .setReadTimeout(Duration.ofMillis(configuration.getSecurityRestReceiveTimeout()));

// my normal restTemplate
RestTemplateBuilder restTemplate = genericBuilder
                .defaultMessageConverters()
                .build();

// HAL specific restTemplate                
RestTemplateBuilder restTemplateHal = genericBuilder
                .messageConverters(getHalConverter(Arrays.asList(MediaTypes.HAL_JSON)))
                .build();

The HalConverter is generated like this (registering also JavaTimeModule):

   private static HttpMessageConverter<?> getHalConverter(List<MediaType> halFlavours) {

        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new Jackson2HalModule());
        mapper.registerModule(new JavaTimeModule());
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();

        converter.setObjectMapper(mapper);
        converter.setSupportedMediaTypes(halFlavours);

        return converter;
    }

Then you can use Traverson in setting the just generated restTemplateHal

    Traverson traverson = new Traverson(uri, MediaTypes.HAL_JSON);
    traverson.setRestOperations(restTemplateHal);
    MyClass myclass = traverson.follow().toObject(MyClass.class);
Top answer
1 of 2
7

I remember I did not have this problem with older versions of spring (or maybe I was LUCKY) But this is how I solved it in Spring boot 2.1.7.RELEASE:

First, add Jackson's support modules in order to support Java 8 features (TimeDate API)

    <dependency>
        <groupId>com.fasterxml.jackson.module</groupId>
        <artifactId>jackson-module-parameter-names</artifactId>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.datatype</groupId>
        <artifactId>jackson-datatype-jdk8</artifactId>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.datatype</groupId>
        <artifactId>jackson-datatype-jsr310</artifactId>
    </dependency>

Then register a default ObjectMapper bean with custom configurations (to support Java 8) in the Spring.

@Bean
@Primary
public ObjectMapper geObjMapper(){
    return new ObjectMapper()
            .registerModule(new ParameterNamesModule())
            .registerModule(new Jdk8Module())
            .registerModule(new JavaTimeModule());
}

NOTE: @Primary is used as a precautionary measure, so if there are other ObjectsMapper beans on the class-path, the spring will pick this one by default.

2 of 2
1

The solution you wrote is right approach. Other approaches are mentioned below. public class LocalDateTimeSerializer implements JsonSerializer { @Override public JsonElement serialize(LocalDateTime localDateTime, Type type, JsonSerializationContext jsonSerializationContext) { Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant(); Date date = Date.from(instant); return new JsonPrimitive(date.getTime()); } }

GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(LocalDateTime.class, new LocalDateTimeSerializer());

Gson gson = gsonBuilder.create();

Another approach. Any way try this . try to change date time format to string. "2011-04-08T09:00:00". The nano and other format are so complex I cannot tell from your lastseen json what datetime exactly you are talking about. It misses Time zone too so your local time can be anywhere you deploy solution,If you deploy in 3 different time zone machines local time is not correct. Use this string format or make your own "2011-04-08T09:00:00"

public class CustomJsonDateDeserializer extends JsonDeserializer<Date>
{
    @Override
    public Date deserialize(JsonParser jsonParser,
            DeserializationContext deserializationContext) throws IOException, JsonProcessingException {

        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
        String date = jsonParser.getText();
        try {
            return format.parse(date);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }

    }

}

@JsonDeserialize(using = CustomJsonDateDeserializer.class)
🌐
HowToDoInJava
howtodoinjava.com › home › jackson › jackson error: java 8 date/time type not supported by default
Jackson Error: Java 8 date/time type not supported by default
June 18, 2023 - @Provider @Priority(value = 1) @Consumes({"application/json", "application/*+json", "text/json"}) @Produces({"application/json", "application/*+json", "text/json"}) public class CustomJsonProvider extends JacksonJsonProvider { private static final ObjectMapper OBJECT_MAPPER; static { // create the one and only instance OBJECT_MAPPER = LuminObjectMapper.getInstance(); } public CustomJsonProvider() { super(OBJECT_MAPPER); } } Reply · Thanks for sharing. Reply · Works for me, when using Postman to send GET and PUT requests! But does not work, when using REST-Client from my WebApp to send PUT request. This results in error: RESTEASY004655: Unable to invoke request: java.lang.RuntimeException: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Java 8 date/time type java.time.LocalDateTime not supported by default
🌐
JetBrains
youtrack.jetbrains.com › issue › KTIJ-21598 › Scratch-REPL-InvalidDefinitionException-Cannot-construct-instance-of-with-Jackson-ObjectMapper-and-Use-REPL
Cannot construct instance of" with Jackson ObjectMapper ...
Our website uses some cookies and records your IP address for the purposes of accessibility, security, and managing your access to the telecommunication network. You can disable data collection and cookies by changing your browser settings, but it may affect how this website functions.
🌐
Baeldung
baeldung.com › home › json › jackson › jackson exceptions – problems and solutions
Jackson Exceptions - Problems and Solutions | Baeldung
April 8, 2024 - Use Jackson to map custom JSON to any java entity graph with full control over the deserialization process. ... First, let’s take a look at JsonMappingException: Can Not Construct Instance Of.