How to parse LocalDate with Jackson - java

I am facing problem passing date as json data through postman. In case of Mandetory date with #NotNull annotation, no problem. The other date is accepting null. But at the time of updation, that date creates problem.
I am using Java 1.8 with spring boot & MySql DB. Please help
The following links I have visited, but does not fit with this.
LocalDateTime parsing with jackson
JSON parse error: Can not construct instance of java.time.LocalDate: no String-argument constructor/factory method to deserialize from String value
https://stackoverflow.com/a/29959842/3415090
JSON Java 8 LocalDateTime format in Spring Boot
I have also used
#JsonSerialize(using = LocalDateSerializer.class)
#JsonDeserialize(using = LocalDateDeserializer.class)
But problem remains as it is.
My UX
public class LeaveApplUx {
#JsonIgnore
#Size(max = 5, message = "Employee Code Must Be Within 4 To 5 Character Long Or Blank")
private final String employeeCode;
#NotNull(message = "Start Date Empty")
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy")
private final LocalDate startDate;
#JsonIgnore
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy")
private final LocalDate rejoinDate;
public LeaveApplUx(
#Size(min = 4, max = 5, message = "Employee Code Must Be Within 4 To 5 Character Long Or Blank")
#JsonProperty("employeeCode") String employeeCode,
#NotNull(message = "Start Date Empty") #JsonProperty("startDate") LocalDate startDate,
#JsonProperty("rejoinDate") LocalDate rejoinDate) {
this.employeeCode = employeeCode;
this.startDate = startDate;
this.rejoinDate = rejoinDate;
}
// GETTERS
}
At the time of creation, it works fine.
{
"employeeCode": "B426",
"startDate": "01-03-2023"
}
Input Parameters : {"employeeCode":"B426","startDate":{"year":2023,"month":"MARCH","monthValue":3,"dayOfMonth":1,"leapYear":false,"dayOfWeek":"WEDNESDAY","dayOfYear":60,"era":"CE","chronology":{"id":"ISO","calendarType":"iso8601"}},"rejoinDate":null}
Record saved properly in DB
But at the time of updation, it creates error.
{
"employeeCode": "B426",
"startDate": "01-03-2023",
"rejoinDate": "06-03-2023"
}
JSON parse error:
Cannot deserialize value of type `java.time.LocalDate` from String "06-03-2023": Failed to deserialize java.time.LocalDate: (java.time.format.DateTimeParseException) Text '06-03-2023' could not be parsed at index 0; nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.time.LocalDate` from String "06-03-2023": Failed to deserialize java.time.LocalDate: (java.time.format.DateTimeParseException) Text '06-03-2023' could not be parsed at index 0
at [Source: (PushbackInputStream); line: 14, column: 19] (through reference chain: org.myapp.ux.hr.leave.LeaveApplUx["rejoinDate"])

Since you set values through contructor, not setters, you should put #JsonFormat(...) on constructor parameters, not fields. This should fix it:
public class LeaveApplUx {
#JsonIgnore
private final String employeeCode;
private final LocalDate startDate;
#JsonIgnore
private final LocalDate rejoinDate;
public LeaveApplUx(#JsonProperty("employeeCode") String employeeCode,
#JsonProperty("startDate") #JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy") LocalDate startDate,
#JsonProperty("rejoinDate") #JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy") LocalDate rejoinDate) {
this.employeeCode = employeeCode;
this.startDate = startDate;
this.rejoinDate = rejoinDate;
}
//getters
}

Related

Populating custom field through jackson

I have a POJO as below:
#Data
#Builder
#AllArgsConstructor
#NoArgsConstructor
#JsonIgnoreProperties(ignoreUnknown = true)
public class CalendarData {
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd/MM/yyyy HH:mm:ss")
// field to contain formatted date as per clients requirement - shud be mirror of "date"
private String formattedDate;
private long date;
private String errorCode;
private String subErrorCode;
}
Downstream service is only sending date field as epoch and i want to have the formattedDate populated in run time in given format.
I can always write a custom function to format the data, but want to understand is there any native jackson way or custom setter to do that.
You're almost doing it right. However having a #JsonFormat-Annotation on a String field does not make to much sense, because if it already is String, there is nothing to convert for Jackson anymore. You can just make both fields of type Date and the #JsonFormat annotation on the formattedDate field will serialize it into the proper JSON String representation, exactly in the format you specified in the pattern. Jackson will by default serialize all java.util.Date Object of an object it needs to serialize into the epoch milliseconds as a regular JSON number. So this would work for you. However, as both fields in the final JSON will refer to the exact same Date object it feels weird to have them both as fields of the CalendarData object. I would suggest you just give CalendarData a single field date and then create a getter method for the formattedDate field. Here is what this could look like. By default Jackson will pick up all getter functions and serialize their returned data into the generated json object.
#Data
#JsonIgnoreProperties(ignoreUnknown = true)
public class CalendarData {
CalendarData(final Date date) {
this.date = date;
}
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd/MM/yyyy HH:mm:ss")
private Date getFormattedDate(){
return this.date;
};
private Date date;
}
UPDATE
As you updates you question I also want to update my answer. I recommend you the following (analogous to what I already explained above).
#Data
#Builder
#AllArgsConstructor
#NoArgsConstructor
#JsonIgnoreProperties(ignoreUnknown = true)
public class CalendarData {
private Date date;
private String errorCode;
private String subErrorCode;
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd/MM/yyyy HH:mm:ss")
// field to contain formatted date as per clients requirement - shud be mirror of "date"
private Date getFormattedDate(){
return this.date;
};
}
Then in my main I tried it out
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
CalendarData data = CalendarData.builder()
.errorCode("23")
.subErrorCode("42")
.date(new Date())
.build();
System.out.println(mapper.writeValueAsString(data));
}
Which perfectly prints out
{
"date": 1676642216673,
"errorCode": "23",
"subErrorCode": "42",
"formattedDate": "17/02/2023 13:56:56"
}

Getting "JSON Binding deserialization" error while json mapping to object

Getting below error while deserialization
javax.ws.rs.client.ResponseProcessingException: javax.ws.rs.ProcessingException: RESTEASY008200: JSON Binding deserialization error: javax.json.bind.JsonbException: Unable to deserialize property 'birthDate' because of: Error parsing class java.util.Date from value: 1999-04-11. Check your #JsonbDateFormat has all time units for class java.util.Date type, or consider using org.eclipse.yasson.YassonProperties#ZERO_TIME_PARSE_DEFAULTING.
I have added below annotations still not working
#JsonDeserialize(using = LocalDateDeserializer.class)
#JsonProperty
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
#JsonbProperty
#JsonbDateFormat(value = "yyyy-MM-dd", locale = "Locale.ENGLISH")
public Date getbirthDate() {
return birthDate;
}
for my class, I was using localdatetime. I had to add this anotation over the entity column
#JsonDeserialize(using = LocalDateTimeDeserializer.class)
#JsonSerialize(using = LocalDateTimeSerializer.class)
public LocalDateTime effectiveTimestamp;

Java LocalDate - Time gets appended onto date when saving in MongoDB?

I have the following Java Entity:
public class Round {
private ObjectId _id;
#NotEmpty
#Getter
#Setter
#Accessors(fluent = true)
#JsonProperty("userId")
private String userId;
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy")
#JsonDeserialize(using = LocalDateDeserializer.class)
#JsonSerialize(using = LocalDateSerializer.class)
#Getter
#Setter
#Accessors(fluent = true)
#JsonProperty("date")
private LocalDate date;
//other fields
}
When I do a POST to my Spring Boot REST web app with JSON Body:
{
"userId": "user3",
"date": "20-01-2020"
}
The date is persisted in Mongo as follows:
2020-01-20T00:00:00.000+00:00
How can I get the date to persist as simply:
20-01-2020
It's not Java problem, MongoDB uses Date format similar to JavaScript Date format.
If you want to save just dd-MM-YYYY you may want to change your column type to String.
If it's not possible then you need to rewrite your serializer to return String representation of date (and of course rewrite deserializer to parse that string into LocalDate

Entity data types must be same as param into JPA repository?

I try to use JPA Repository to get data from my database. Here I want get all MyObject between startdate and enddate.
Code
Repository
#GetMapping
List<Tache> getMyObjectsByStartdateAfterAndEnddateBefore(#RequestParam Date startdate,
#RequestParam Date enddate);
Controller
#GetMapping(params = {"startdate", "enddate"})
public ResponseEntity<?> findAllByStartdateAfterAndEnddateBefore(#RequestParam("startdate") String startdate,
#RequestParam("enddate") String enddate) throws ParseException {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
Date start = formatter.parse(startdate);
Date end = formatter.parse(enddate);
return new ResponseEntity<>(this.tacheResource.getMyObjectsByStartdateAfterAndEnddateBefore(start, end), HttpStatus.OK);
}
Entity
#Entity
public class MyObject {
#Id
private String id;
#ColumnDefault("CURDATE()")
private String startdate;
private String enddate;
...
}
GET request example
http://localhost:8082/myobject/?startdate=2019-02-19&enddate=2019-06-01
Error (into Repository)
Expected parameter types : String, String
However, I don't understand why because I defined the method with Date type as parameter. Is it because dates are stored as String into my entity?
Your Entities startdate and enddate data types should be Date too in order to get objects with date parameters
#Entity
public class MyObject {
#Id
private String id;
#ColumnDefault("CURDATE()")
private Date startdate;
private Date enddate;
...
}
It should always be a match between jpa method params and your class fields type. In your case, if MyObject has String fields (startDate and endDate), the jpa method should receive String param.
For your particular example, it seems more natural to have your MyObject class with Date fields instead of String:
#Entity
public class MyObject {
#Id
private String id;
#ColumnDefault("CURDATE()")
private Date startdate;
private Date enddate;
...
}
In this way, you will be able to pass Date objects as params to your JPA method.

Spring Date Format

I have an angular app which send me a date like this dd/MM/yyyy.
I would like to insert this date in the database.
Here is my entity
#Entity
public class Individu implements Serializable {
#Id
private String nui;
private int civility;
private String lastName;
private String useName;
private String firstName;
#Temporal(TemporalType.DATE)
#DateTimeFormat(pattern="dd/MM/yyyy")
private Date birthDate;
but when i run my SpringBootApp i always have this error:
org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `java.util.Date` from String "20/02/1990": not a valid representation (error: Failed to parse Date value '20/02/1990': Cannot parse date "20/02/1990": not compatible with any of standard forms ("yyyy-MM-dd'T'HH:mm:ss.SSSZ", "yyyy-MM-dd'T'HH:mm:ss.SSS", "EEE, dd MMM yyyy HH:mm:ss zzz", "yyyy-MM-dd"));
Is some one have a solution for me?
You need #JsonFormat:
#JsonFormat(pattern="dd/MM/yyyy")
private Date birthDate;

Categories