Cannot construct instance of `java.time.LocalDate` - Spring boot, elasticseach, jackson
Solution 1
add below annotation over the field LocalDate
@JsonDeserialize(using = LocalDateDeserializer.class)
@JsonSerialize(using = LocalDateSerializer.class)
private LocalDate start;
Solution 2
Date/time format, according to ISO 8601 is "YYYY-MM-DD", so your pattern should be:
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
Instead of:
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd.MM.yyyy")
Another way is adding in your application.yml
spring:
jackson:
serialization:
WRITE_DATES_AS_TIMESTAMPS: false
Or disable this feature directly in your object mapper:
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
Solution 3
need to install JsonFormat JsonDeserialize JsonSerialize
private LocalDate dateOfBirth;
@PastOrPresent(message = "must be past time or present")
@Column(name = "date_of_birth", nullable = false, columnDefinition = "DATE")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy")
@JsonDeserialize(using = LocalDateDeserializer.class)
@JsonSerialize(using = LocalDateSerializer.class)
public LocalDate getDateOfBirth() {
return dateOfBirth;
}
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy")
public void setDateOfBirth(LocalDate dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}
Related videos on Youtube
Comments
-
Patrick almost 2 years
I'm using
Spring-boot 2.0.0.M7
andspring-boot-starter-data-elasticsearch
andelasticsearch 5
and I'm getting an error by deserializing aLocalDate
field.My Document looks like that:
@Document(indexName= "myIndex", type = "cluster") public class Cluster { @Id @Field private Long id; @Field private String name; @Field private ClusterUrl clusterUrl; @Field private ClusterVisible clusterVisible; }
Where ClusterVisible is a child object which holds the
LocalDates
:public class ClusterVisible { @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd.MM.yyyy") private LocalDate start; @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd.MM.yyyy") private LocalDate end; }
So I just make a query for one cluster Id and I get this exception:
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `java.time.LocalDate` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator) at [Source: (String)"{"id":12345,"name":"Cluster name ","clusterName":{"de":"Cluster de","it":null,"fr":null},"clusterUrl":{"de":"/url/results","it":null,"fr":null},"clusterVisible":{"start":{"year":2017,"month":"OCTOBER","dayOfMonth":9,"dayOfWeek":"MONDAY","era":"CE","dayOfYear":282,"leapYear":false,"mo"[truncated 252 chars]; line: 1, column: 388] (through reference chain: com.example.elasticsearch5.es.cluster.model.Cluster["clusterVisible"]->com.example.elasticsearch5.es.cluster.model.ClusterVisible["start"]) at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67) at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1451) at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1027) at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1290) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:326) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:159) at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:127) at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:288) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151) at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:127) at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:288) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151) at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4001) at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2992) at org.springframework.data.elasticsearch.core.DefaultEntityMapper.mapToObject(DefaultEntityMapper.java:65)
I already know that I need to add some jackson dependencies for the
java.time api
so I added:<dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jsr310</artifactId> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.4</version> </dependency>
But this does not help for now. I also checked the entry in the index by making a query using kibana. The result of the query is:
... "clusterVisible": { "start": { "year": 2017, "month": "OCTOBER", "dayOfMonth": 25, "dayOfWeek": "WEDNESDAY", "era": "CE", "dayOfYear": 298, "leapYear": false, "monthValue": 10, "chronology": { "id": "ISO", "calendarType": "iso8601" } }, "end": { "year": 3000, "month": "JANUARY", "dayOfMonth": 1, "dayOfWeek": "WEDNESDAY", "era": "CE", "dayOfYear": 1, "leapYear": false, "monthValue": 1, "chronology": { "id": "ISO", "calendarType": "iso8601" } } }
What do I miss for fixing this error?
Addition: The exact error occours at
mapper.mapToObject
. So I created anew DefaultEntityMapper();
some lines before. Could that be the issue?@Override public Page<Cluster> findClustersAndScoreByText(String text) { QueryBuilder queryBuilder = QueryBuilders.boolQuery() .should(QueryBuilders.queryStringQuery(text).lenient(true).defaultOperator(Operator.OR) .field("name") .field("svno")); NativeSearchQuery nativeSearchQuery = new NativeSearchQueryBuilder().withQuery(queryBuilder) .withPageable(PageRequest.of(0, 100)).build(); DefaultEntityMapper mapper = new DefaultEntityMapper(); ResultsExtractor<Page<Cluster>> rs = new ResultsExtractor<Page<Cluster>>() { @Override public Page<Cluster> extract(SearchResponse response) { ArrayList<Cluster> hotels = new ArrayList<>(); SearchHit[] hits = response.getHits().getHits(); for (SearchHit hit : hits) { try { Cluster cluster = mapper.mapToObject(hit.getSourceAsString(), Cluster.class); cluster.setScore(hit.getScore()); hotels.add(cluster); } catch (IOException e) { e.printStackTrace(); } } return new PageImpl<>(hotels, PageRequest.of(0, 100), response.getHits().getTotalHits()); } }; return elasticsearchTemplate.query(nativeSearchQuery, rs); }
-
OneCricketeer about 6 yearsYour start and end data are objects... Why would
pattern = "dd.MM.yyyy"
work? -
Patrick about 6 years@cricket_007 should be ok for deserializing to the frontend. But I removed it and there is no change.
-
OneCricketeer about 6 yearsThe error is telling you that no default constructor exists for a localdatetime and its an immutable class, so it can't just call
setters
for each field in the json. Why don't you write your own class for that object? -
Patrick about 6 years@cricket_007 if the config does not work I need to write my own class. I autowired the jackson object mapper instead using a new one, I get another exception for localdate:
com.fasterxml.jackson.databind.exc.MismatchedInputException: Unexpected token (START_OBJECT), expected VALUE_STRING: Expected array or string.
any idea? -
OneCricketeer about 6 years
"start": {
is an object, as the error says.JsonFormat.Shape.STRING
is trying to parse a string, which you don't have
-
-
user1428716 over 4 yearsthis solution would not work if these are auto-generated stubs. Answer by @evdelacruz is more valid
-
Dimitri Kopriwa about 3 yearsHow can I disable the serialization for one request and not all of them?
-
evdelacruz about 3 years@DimitriKopriwa, the ObjectMapper is a bean that is built within the ApplicationContext to be injected as needed. I'm afraid u will need to use Jackson custom annotations to achieve that. Another possibility is to treat the field as a String within the DTO/VO/TO and then parse it as desired within that specific scenario/request.
-
Irinel about 2 yearsit's not enough