In our code we currently use the Jackson #JsonFormat annotation on a date object as follows:
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ssZZ")
private Date startDate;
Is there a class which defines constants for these patterns in order to avoid having such hardcoded value? Something like:
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = DateTimePatterns.ISO_DATETIME_TIMEZONE)
private Date startDate;
Or should I just create my own constants-class?
Related
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"
}
I have a class like this. I want to enforce that the two Date fields should take in the request only if the date in request comes in a valid ISO Date time format like: 2021-01-19T12:20:35+00:00
#Data
#AllArgsConstructor
#NoArgsConstructor
#Builder
#Validated
public class EDDDetail {
#NotBlank
private String versionId;
#NotNull
private Date minTime;
#NotNull
private Date maxTime;
}
How to achieve this? Currently this accepts a date in long format (epoch time [e.g.: 1611058835000] ) and other valid dates as well like 22-02-2021 etc.
I want to throw a bad request if the date format in the request is not an ISO format date.
You can use #JsonFormat annotation with provided pattern to format the date
E.g:
#JsonFormat(pattern = "yyyy-MM-dd")
You can use the #JsonFormat annotation to define your pattern:
#NotNull
#JsonFormat(pattern="dd-MM-yyyy")
private Date minTime;
#NotNull
#JsonFormat(pattern="dd-MM-yyyy")
private Date maxTime;
If you want to accept multiple patterns you can get some implementation on this link: Configure Jackson to parse multiple date formats
I need to validate date with pattern 'yyyy-MM-dd HH:mm:ss'. I'm using util date with jackson version 2.10.2
and I can't move to java 8 localdate as company requirement. I found many Q&A regarding this issue and none of them solve my problem properly.
import com.fasterxml.jackson.annotation.*;
import lombok.Data;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.Date;
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({
"provisionedDate",
})
#Data
#JsonIgnoreProperties(ignoreUnknown = true)
#JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY,
getterVisibility = JsonAutoDetect.Visibility.NONE,
setterVisibility = JsonAutoDetect.Visibility.NONE)
public class PostProvisionCallback implements Serializable {
#JsonProperty("id")
private String id;
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
#NotNull(message = "provisionedDate cannot be null")
#JsonProperty("provisionedDate")
private Date provisionedDate;
}
even I enter invalid date like '20201-0612213-17 09:26:12',still this is evaluate as valid date. What is the perfect solution for this.? but if I enter date as '2020/03/04 09:26:12' then application throw internal server error exception.
It is the SimpleDateFormat that handles the actual configurable parsing. You can set the value of lenient as false.
Replace
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
with
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", lenient = OptBoolean.FALSE)
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
#Data
public class Reponse {
private String event;
#Temporal(TemporalType.TIMESTAMP)
private Date eventDate;
private Double amount;
}
Json response is like
{
event: "transcation',
eventDate: 1213123434,
amount: 100
}
Here, eventDate is showing numeric value 1540317600000 instead of 2018-10-23
You can annotated the field with #JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm"). Then, response time format will be like "yyyy-MM-dd HH:mm"
import com.fasterxml.jackson.annotation.JsonFormat;
public class Reponse {
private String event;
#Temporal(TemporalType.TIMESTAMP)
#JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm")
private Date eventDate;
private Double amount;
}
If you use Spring boot 2.x instead 1.x ,the default behavior has changed
add spring.jackson.serialization.write-dates-as-timestamps=true to your configuration to return to the previous behavior
Spring Boot 2.0 Migration Guide
spring 2.x flipped a Jackson configuration default to write JSR-310 dates as ISO-8601 strings. If you wish to return to the previous behavior, you can add
spring.jackson.serialization.write-dates-as-timestamps=true
to your application-context configuration file.
I suppose you are using rest framework such as spring boot or jersey which in turn
converts your java date into epoch format before sending it to the client. So while
sending response you can format you date into the format you want. Please refer
the code below.
import java.text.SimpleDateFormat;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");
sdf.setLenient(false);
String responseDate = sdf.format(date);