Home > Enterprise >  How to parse properly Date string to java.util.Date when deserializing JSON to Java POJO with Jackso
How to parse properly Date string to java.util.Date when deserializing JSON to Java POJO with Jackso

Time:11-10

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;
    }
  • Related