Unparseable date while POST date application/json from PostMan - java

I get unparseable date exception. After a lot of searches, I try with Locale.US and Locale.ENGLISH and with dateFormat: "yyyy-MM-dd HH:mm:ss z" but still the same error. So I try with an annotation from Jackson-dataFormat so I got this with this pattern and try with the pattern "yyyy-MM-dd HH:mm:ss z" too:
#Column(name="date", nullable=false)
#Temporal(TemporalType.DATE)
#JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd'T'HH:mm:ssZ")
private Date date;
My dateInString is: "2017-12-23T20:30:15.000Z".
I don't really know where can be the exception.
try {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US);
this.date = (Date)formatter.parse(dateInString);
}
catch(ParseException e) {
e.printStackTrace();
}
Maybe this information will help. In my Database, the column is named the date and is DATE type. (I have the choice in phpMyAdmin to choose DATE or DATETIME type).
At the beginning, I thought it was because I forgot the Locale.X parameter but still the exception.
Errors:
Caused by: com.owlike.genson.JsonBindingException: Could not parse date 2017-12-23T20:30:15.000Z
at com.owlike.genson.convert.DefaultConverters$DateConverter.deserialize(DefaultConverters.java:815)
at com.owlike.genson.convert.DefaultConverters$DateConverter.deserialize(DefaultConverters.java:781)
at com.owlike.genson.convert.NullConverter$NullConverterWrapper.deserialize(NullConverter.java:57)
at com.owlike.genson.reflect.PropertyMutator.deserialize(PropertyMutator.java:30)
... 46 more
Caused by: java.text.ParseException: Unparseable date: "2017-12-23T20:30:15.000Z"
at java.text.DateFormat.parse(DateFormat.java:366)
at com.owlike.genson.convert.DefaultConverters$DateConverter.read(DefaultConverters.java:821)
at com.owlike.genson.convert.DefaultConverters$DateConverter.deserialize(DefaultConverters.java:813)
... 49 more
So I get this errors too but it's because my parsing not work:
Caused by: com.owlike.genson.JsonBindingException: Could not deserialize to type class model.SessionActivity
at com.owlike.genson.Genson.deserialize(Genson.java:442)
at com.owlike.genson.ext.jaxrs.GensonJsonConverter.readFrom(GensonJsonConverter.java:125)
... 40 more
Caused by: com.owlike.genson.JsonBindingException: Could not deserialize to property 'date' of class class model.SessionActivity
at com.owlike.genson.reflect.PropertyMutator.couldNotDeserialize(PropertyMutator.java:49)
at com.owlike.genson.reflect.PropertyMutator.deserialize(PropertyMutator.java:32)
at com.owlike.genson.reflect.BeanDescriptor.deserialize(BeanDescriptor.java:110)
at com.owlike.genson.reflect.BeanDescriptor.deserialize(BeanDescriptor.java:93)
at com.owlike.genson.convert.BeanViewConverter.deserialize(BeanViewConverter.java:105)
at com.owlike.genson.convert.NullConverter$NullConverterWrapper.deserialize(NullConverter.java:57)
at com.owlike.genson.Genson.deserialize(Genson.java:440)
... 41 more
The subject already exist, I read them and try to resolve with these responses but none work actually.
Here is my POST json request:
Trying with ISO 8601: 2017-12-23T20:30:15.000Z
First, I handle POST request in WebService class:
#POST
#Path("/")
#Consumes(MediaType.APPLICATION_JSON)
public Response addSession(SessionActivity sessionActivity) {
SessionDAO.add(sessionActivity);
return Response.ok().build();
}
It call add() of DAO session:
public static void add(SessionActivity sessionActivity){
try {
session = SessionUtil.getSession();
Transaction tx = session.beginTransaction();
session.save(sessionActivity);
tx.commit();
session.close();
}
catch(Exception e) {
System.out.println( "ADD sessionActivity non effectué :" );
e.printStackTrace();
}
}
Then here is my model:
#Column(name="date", nullable=false)
#Temporal(TemporalType.DATE)
#JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd'T'HH:mm:ssZ")
private Date date;
public SessionActivity(Long id, User user, Date date) {
super();
this.id = id;
this.user = user;
this.date = date;
/*
try {
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US);
this.date = (Date)formatter.parse(dateInString);
}
catch(ParseException e) {
e.printStackTrace();
}*/
}

The format for a json date is ISO 8601: 2017-12-23T20:30:15.000Z
A json coming with a value like this should parse into a java Date without having to do any conversion. The same the other way round.
By the way, Z at the end means it a Zulu or GMT 0 time. So after the value is parsed into a java Date you can use time zoned methods to get the value for a specific locale.
EDIT I
I think there is some issue with the parser you are using. I ran a test using the Genson parser you are using and the same test using Gson, with the same json text, and while Genson couldn't parse the date, Gson parsed it with no problem.
Here is the test, you have to comment the lines you don't want to execute.
Also note I had to annotate the DatedObject class constructor for Genson to find it (public DatedObject(#JaonParam("date") Date date, JsonParam("user") String user){)
import com.google.gson.Gson;
import com.owlike.genson.Genson;
import com.owlike.genson.annotation.JsonProperty;
public class JsonParseDate {
public String json = "{\"date\":\"2017-12-23T20:30:15.000Z\",\"user_fk\":\"1\"}";
public static void main(String [] args){
JsonParseDate app = new JsonParseDate();
app.go();
}
private void go(){
// Comment next two lines to run with Gson (and uncomment the Gson lines)
// Genson genson = new Genson();
// DatedObject datedObject = genson.deserialize(json, DatedObject.class);
// Comment next two lines to run with Genson (and uncomment Genson lines)
Gson gson = new Gson();
DatedObject datedObject = gson.fromJson(json, DatedObject.class);
System.out.println(datedObject.date);
}
public static class DatedObject{
public Date date;
public String user;
public DatedObject(Date date, String user){
this.date = date;
this.user = user;
}
}
}
Ref to Genson user guide
For Gson you can get the jar from maven or add the dependancy to your pom if you are using maven.

Related

JSON deserialization problem - error parsing Instant

I need to persist object in Azure Table Storage. Problem is I don't want to use Date type in my Entity class. I would like to use Instant but I have problems with parsing with the JasonMappingException.
Here is my entity class:
#Data
public class Event extends TableServiceEntity {
#NotNull
#JsonDeserialize(using = JsonDateDeserializer.class)
private Instant eventStart;
#NotNull
#JsonDeserialize(using = JsonDateDeserializer.class)
private Instant eventEnd;
#NotBlank
private String eventName;
private String eventDescription;
//default constructor
public Event () {}
}
And here is my deserializer:
public class JsonDateDeserializer extends JsonDeserializer<Instant> {
#Override
public Instant deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
String date = jsonParser.getText();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
try {
return sdf.parse(date).toInstant();
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
}
I am getting this error:
2020-06-10 20:47:19.685 WARN 11745 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: java.text.ParseException: Unparseable date: "2020-06-12T08:00:00UTC"; nested exception is com.fasterxml.jackson.databind.JsonMappingException: java.text.ParseException: Unparseable date: "2020-06-12T08:00:00UTC" (through reference chain: com.komix.eventmanager.model.Event["eventStart"])]
I am soo tired of the date problems with Azure DB. Could you please help me?
EDIT: Ok, after some edit parsing is fine but application gives me following error:
java.lang.IllegalArgumentException: Type class java.time.Instant is not supported.
It seems that Azure Table Storage doesn't support Instant??! I can't even find any good documentation for Asure Table data types supported...
'Z' is considered here as constants. You need to pass z without the quotes.
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssz");
Doc ref here

How to dynamically customise deserialiser for date format?

I am working on custom JSON deserialiser and have the below class
public class yyyy_MM_dd_DateDeserializer extends StdDeserializer <LocalDate> {
public yyyy_MM_dd_DateDeserializer() {
this(null);
}
public yyyy_MM_dd_DateDeserializer(Class t) {
super(t);
}
#Override
public LocalDate deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
String dateString = jsonParser.getText();
LocalDate localDate = null;
try {
localDate = LocalDate.parse(dateString, "yyyy-MM-dd");
} catch (DateTimeParseException ex) {
throw new RuntimeException("Unparsable date: " + dateString);
}
return localDate;
}
}
and in my request class
#Valid
#JsonDeserialize(using = LocalDateDeserializer.class)
#JsonSerialize(using = LocalDateSerializer.class)
private LocalDate endDate;
It works fine but I am wondering if I can pass the date format dynamically. Instead of hardcoding in yyyy_MM_dd_DateDeserializer.
I want to pass the date format from my request class so that my deserialiser is more generic any anyone can use it by sending the required format.
I think you working too hard to get what you want. There is a simpler way without writing your own deserializer. Look at this question. Essentially it looks like
#JsonFormat(shape= JsonFormat.Shape.STRING, pattern="EEE MMM dd HH:mm:ss Z yyyy")
#JsonProperty("created_at")
ZonedDateTime created_at;
And you just put your own mask. Also, I once had a task of parsing date with unknown format, essentially I needed to parse any valid date. Here is an article describing the idea of how to implement it: Java 8 java.time package: parsing any string to date. You might find it useful
Not when using a binder library (The very point of binding is that it is not dynamic.).
But you could when using a simple parsing library such as org.json
When you are working with java.time.* classes and Jackson is good to start from registering JavaTimeModule which comes from jackson-datatype-jsr310 module. We can extend it and register serialiser with provided pattern like in below example:
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class JsonApp {
public static void main(String[] args) throws Exception {
ObjectMapper mapperIso = createObjectMapper("yyyy-MM-dd");
ObjectMapper mapperCustom0 = createObjectMapper("yyyy/MM/dd");
ObjectMapper mapperCustom1 = createObjectMapper("MM-dd-yyyy");
System.out.println(mapperIso.writeValueAsString(new Time()));
System.out.println(mapperCustom0.writeValueAsString(new Time()));
System.out.println(mapperCustom1.writeValueAsString(new Time()));
}
private static ObjectMapper createObjectMapper(String pattern) {
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(pattern)));
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(javaTimeModule);
return mapper;
}
}
class Time {
private LocalDate now = LocalDate.now();
public LocalDate getNow() {
return now;
}
public void setNow(LocalDate now) {
this.now = now;
}
#Override
public String toString() {
return "Time{" +
"now=" + now +
'}';
}
}
Aboce code prints:
{"now":"2019-02-24"}
{"now":"2019/02/24"}
{"now":"02-24-2019"}

From post man(rest service) how to send json date(string format) to java which accepts date object

How to bind dateOfJoining value(String type) to member variable "dateOfJoining"(Date type) in "DateInput" Class after sending below JSON through postman. How to convert String to Date object in java with the same format dd/MM/yyyy. Converted date should be in Date object but not String.
Json is as given below
{
"dateOfJoining" : "03/04/2017"
}
Service URL hitting in postman -- localhost/Rest/hello
RestService class in java - HandleRestRequest.java
#RestController
public class HandleRestRequest
{
#RequestMapping("\hello");
public List setRequestParams(#RequestBody DateInput dateInput)
{
.......
}
}
Pojo Class DateInput.java
public class DateInput
{
private Date dateOfJoining;
.......
}
If I send date from json in below format, its throwing error as unsatisfied input
{
"dateOfJoining" : 04/04/2017
}
So I sending it as string format and by changing dateOfJoining as string in DateInput.java file and later I tried to convert it as date object as below
Modified DateInput.java file from Date to String
public class DateInput
{
private String dateOfJoining;
.......
}
Modified JSON
{
"dateOfJoining" : "04/04/2017"
}
Code to convert user input from String to Date
DateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
String convertedDate = sdf.format(dateInput.getDateOfJoining());
Its converting into required format but return type is String but expected is Date object to send DAO layer. So I tried sdf.parse, its returning Date object but not in required format
Date date = sdf.parse(sdf.format(dateInput.getDateOfJoining()));
output is like - Tue Apr 04 00:00:00 IST 2017
expected is 04/04/2017 (with return type Date object).
So please help me how to convert the string to date object with required format since DAO layer is expecting input as date object in format dd/MM/yyyy
Edit: Updating answer in accordance with updated question.
Use annotation #JsonFormat from Jackson Databind to specify the date pattern.
public class DateInput
{
#JsonFormat(shape=JsonFormat.Shape.STRING, pattern="dd-MM-yyyy")
private Date dateOfJoining;
.......
}
With JSON-B (included in Java EE 8) you can do this:
class DateInput {
#JsonbDateFormat("dd/MM/yyyy")
public Date dateOfJoining;
}
In my tests with Thorntail 2.4 I don't need any annotation for ISO format when using java.util.Date:
{
"dateOfJoining" : "2019-04-28T14:45:15"
}
change your code to the below code snippet
public List setRequestParams(#RequestParam("dateOfJoining")#DateTimeFormat(pattern="dd-MM-yyyy") DateInput dateInput)
{
...
}

Unable to convert String to Date by requestBody in spring

I have the below Code :
DTO :
Class MyDTO {
import java.util.Date;
private Date dateOfBirth;
public Date getDateOfBirth() {
return dateOfBirth;
}
public void setDateOfBirth(Date dateOfBirth) {
this.dateOfBirth = dateOfBirth;
}
}
Controller
public void saveDOB(#RequestBody MyDTO myDTO, HttpServletRequest httprequest, HttpServletResponse httpResponse) {
System.out.println("Inside Controller");
System.out.println(myDTO.getDateOfBirth());
}
JSON Request :
{
"dateOfBirth":"2014-09-04",
}
If I send the request as yyyy-mm-dd automatic conversion to date object happens.
output in controller:-
dateOfBirth= Thu Sep 04 05:30:00 IST 2014
But when I send DateofBirth in dd-mm-yyyy format It does not convert String to Date automatically.So how i can i handle this case.
JSON Request :
{
"dateOfBirth":"04-09-2014",
}
Output: No Output in console does not even reaches controller.
I have tried with #DateTimeFormat but its not working.
I am using Spring 4.02 Please suggest is there any annotation we can use.
#DateTimeFormat is for form backing (command) objects. Your JSON is processed (by default) by Jackson's ObjectMapper in Spring's MappingJackson2HttpMessageConverter (assuming the latest version of Jackson). This ObjectMapper has a number of default date formats it can handle. It seems yyyy-mm-dd is one of them, but dd-mm-yyyy is not.
You'll need to register your own date format with a ObjectMapper and register that ObjectMapper with the MappingJackson2HttpMessageConverter. Here are various ways to do that :
Configuring ObjectMapper in Spring
Spring, Jackson and Customization (e.g. CustomDeserializer)
Alternatively, you can use a JsonDeserializer on either your whole class or one of its fields (the date). Examples in the link below
Right way to write JSON deserializer in Spring or extend it
How to deserialize JS date using Jackson?
List itemCreate a class to extend JsonDeserializer
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);
}
}
}
Use #JsonDeserialize(using = CustomJsonDateDeserializer.class) annotation on setter methods.
Thanks #Varun Achar answer, url

How to deserialize JS date using Jackson?

I'm getting a date string from ExtJS in the format:
"2011-04-08T09:00:00"
when i try to deserialize this date, it changes the timezone to Indian Standard Time (adds +5:30 to the time) . This is how i'm deserializing the date:
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
getObjectMapper().getDeserializationConfig().setDateFormat(dateFormat);
Doing this also doesn't change the timezone. I still get the date in IST:
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
getObjectMapper().getDeserializationConfig().setDateFormat(dateFormat);
How do I deserialize the date in the way in which it is coming without the hassles of Timezone?
I found a work around but with this I'll need to annotate each date's setter throughout the project. Is there a way in which I can specify the format while creating the ObjectMapper?
Here's what I did:
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);
}
}
}
And annotated each Date field's setter method with this:
#JsonDeserialize(using = CustomJsonDateDeserializer.class)
This works for me - i am using jackson 2.0.4
ObjectMapper objectMapper = new ObjectMapper();
final DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
objectMapper.setDateFormat(df);
There is a good blog about this topic:
http://www.baeldung.com/jackson-serialize-dates
Use #JsonFormat looks the most simple way.
public class Event {
public String name;
#JsonFormat
(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss")
public Date eventDate;
}
In addition to Varun Achar's answer, this is the Java 8 variant I came up with, that uses java.time.LocalDate and ZonedDateTime instead of the old java.util.Date classes.
public class LocalDateDeserializer extends JsonDeserializer<LocalDate> {
#Override
public LocalDate deserialize(JsonParser jsonparser, DeserializationContext deserializationcontext) throws IOException {
String string = jsonparser.getText();
if(string.length() > 20) {
ZonedDateTime zonedDateTime = ZonedDateTime.parse(string);
return zonedDateTime.toLocalDate();
}
return LocalDate.parse(string);
}
}
#JsonFormat only work for standard format supported by the jackson version that you are using.
Ex :- compatible with any of standard forms ("yyyy-MM-dd'T'HH:mm:ss.SSSZ", "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", "EEE, dd MMM yyyy HH:mm:ss zzz", "yyyy-MM-dd")) for jackson 2.8.6

Categories

Resources