I am implementing an application that gets the data from certin endponts in json formats and tries to deserialize tem to Java Objects but I have problems with the parsing of the date in the JSON.This is how the Date looks like in the JSON: "/Date(1633122000000 0300)/" and I cannot find information in Google how to successfully parse this format.
{
"Date": "/Date(1633122000000 0300)/",
"Filled": 0,
"Needed": 0,
"Paid": 0
}
This is the pojo I use to deserialize the data to using Jackson ObjectMapper:
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class TimeByDateSheet {
@JsonProperty("Date")
@JsonFormat(timezone = "GMT 03:00")
@JsonDeserialize(using = DateDeserializer.class, as=Date.class)
private Date date;
@JsonProperty("Filled")
private Long filled;
@JsonProperty("Needed")
private Long needed;
@JsonProperty("Paid")
private Integer paid;
}
And here is my DateDeserializer:
@SuppressWarnings("serial")
public class DateDeserializer extends JsonDeserializer<Date> {
@Override
public Date deserialize(JsonParser jsonParser, DeserializationContext context)
throws IOException, JsonProcessingException {
SimpleDateFormat simpleDateFormat =
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss zzz", Locale.getDefault());
String dateStr = jsonParser.getText();
Date date;
try{
date = simpleDateFormat.parse(dateStr);
}catch(ParseException e){
throw new RuntimeException(e);
}
return date;
}
}
But it does not work correctly. I get the following exception:
Connected to the target VM, address: '127.0.0.1:52760', transport: 'socket' SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". SLF4J: Defaulting to no-operation (NOP) logger implementation SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: java.text.ParseException: Unparseable date: "/Date(1633035600000 0300)/" (through reference chain: java.util.ArrayList[0]->com.dataart.forecasts.pojo.timebydate.TimeByDateSheet["Date"]) at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:392) at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:351) at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.wrapAndThrow(BeanDeserializerBase.java:1821) at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:315) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:176) at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer._deserializeFromArray(CollectionDeserializer.java:355) at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:244) at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:28) at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:322) at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4675) at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3630) at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3613) at com.dataart.forecasts.DataProcessor.deserializeTimeByDateSheetsList(DataProcessor.java:198) at com.dataart.forecasts.ForecastReportApplication.main(ForecastReportApplication.java:50) Caused by: java.lang.RuntimeException: java.text.ParseException: Unparseable date: "/Date(1633035600000 0300)/" at com.dataart.forecasts.DateDeserializer.deserialize(DateDeserializer.java:28) at com.dataart.forecasts.DateDeserializer.deserialize(DateDeserializer.java:16) at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129) at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:313) ... 10 more Caused by: java.text.ParseException: Unparseable date: "/Date(1633035600000 0300)/" at java.base/java.text.DateFormat.parse(DateFormat.java:395) at com.dataart.forecasts.DateDeserializer.deserialize(DateDeserializer.java:26) ... 13 more
Could someone help me, please. I searched a lot in internet but could not find a solution. Thank you in advance! :)
CodePudding user response:
It looks like there is a problem generating the JSON. I really don't think you want to have the dates formatted like that. Right now, you have some odd text surrounding a unix timestamp in milliseconds followed by a zone offset. You are also using the old and rather frowned-upon Date and SimpleDateFormat classes rather than the newer java.time
API. However, it is possible to deserialize your date format. Here is one way:
public class DateDeserializer extends JsonDeserializer<Date> {
@Override
public Date deserialize(JsonParser jsonParser, DeserializationContext context)
throws IOException, JsonProcessingException {
Pattern pattern = Pattern.compile("/Date\\((\\d )([ -]\\d )\\)/");
Matcher matcher = pattern.matcher(jsonParser.getText());
if (matcher.find()) {
String timestamp = matcher.group(1);
String offset = matcher.group(2);
Instant instant = Instant.ofEpochMilli(Long.parseLong(timestamp));
ZonedDateTime zdt = instant.atZone(ZoneId.of(offset));
instant = zdt.toInstant();
return Date.from(instant);
} else {
throw new RuntimeException("Invalid format: " jsonParser.getText());
}
}
}
CodePudding user response:
@DavidConrad Thank you, I will try your solution. By the way, for now I made a workaround that works for me for now:
@Override
public Date deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException, JsonProcessingException {
SimpleDateFormat dateFormattter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateStr = jsonParser.getText();
String timeZone = dateStr.substring(dateStr.indexOf(" ") 1, dateStr.indexOf(")"));
String timeZoneShift = String.format("%s:%s",
timeZone.substring(0, timeZone.length()/2),
timeZone.substring(timeZone.length()/2));
dateFormattter.setTimeZone(TimeZone.getTimeZone(String.format("GMT %s", timeZoneShift)));
Long millis = 0L;
if (dateStr.contains(" ") && !dateStr.contains("-")) {
millis = Long.parseLong(dateStr.substring(dateStr.indexOf("(") 1, dateStr.indexOf(" ")));
} else if (dateStr.contains(" ") && !dateStr.contains("-")) {
millis = Long.parseLong(dateStr.substring(dateStr.indexOf("(") 1, dateStr.indexOf(")")));
}
Date date = new Date(millis);
String stringDate= dateFormattter.format(date);
try {
date = dateFormattter.parse(stringDate);
} catch (ParseException e) {
throw new RuntimeException(e);
}
return date;
}