Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parsing ASP.NET MVC returned date using Jackson JSON library in Java

I am parsing JSON from server in my Android application by using Jackson JSON library. However, parsing requests fail whenever I receive DateTime since it's in this format:

"/Date(1277931782420)/"

I know I should do something like:

ObjectMapper om = new ObjectMapper();
om.setDateFormat(new TicksSinceFormat());

But I have no idea if I can use SimpleDateFormat at all (and what format string would I use?) or I need to write my own DateFormat parser. So, I would seriously appreciate if somebody could help with code example.

EDIT: OK, see my answer for complete code.

like image 826
nikib3ro Avatar asked Feb 16 '13 04:02

nikib3ro


2 Answers

This proved to be tougher then I expected:

public class TicksSinceFormat extends DateFormat {
    @Override
    public StringBuffer format(Date date, StringBuffer buffer, FieldPosition field) {
        long millis = date.getTime();

        return new StringBuffer("/Date(" + millis + ")/");
    }

    @Override
    public Date parse(String string, ParsePosition position) {
        int start = string.indexOf("(") + 1;
        int end = string.indexOf(")");

        String ms = string.substring(start, end);
        Date date = new Date(Long.parseLong(ms));

        position.setIndex(string.length() - 1); // MUST SET THIS
        return date;
    }

    @Override
    public Object clone() {
        return new TicksSinceFormat(); // MUST SET THIS
    }
}

Using class is then extremely simple, just do:

ObjectMapper om = new ObjectMapper();
om.setDateFormat(new TicksSinceFormat())

I presume that this can be coded better + that I'll need to deal with differences when it comes to .NET Ticks VS Java ticks - but for now this'll do. If somebody has better solution or more insight into mentioned problems I'll deal with later - feel free to post and I'll mark your answer as correct one if it's better.

EDIT: As I've explained in this question & answer I've switched to ServiceStack.Text library on the server and it returns different, ISO8601 format. For that format I'm using slightly different parsing (since Jackson has trouble parsing ISO8601 that contains milliseconds). Of course, as with other code I'm posting - let me know if you have better version (just please post code / edit this post, rather than resorting to philosophical rhetoric on how it should be done):

@SuppressLint("SimpleDateFormat")
public class JacksonSimpleDateFormat extends SimpleDateFormat {
    public JacksonSimpleDateFormat() {
        if (mParser == null) {
            mParser = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
            mParser.setTimeZone(TimeZone.getTimeZone("UTC"));
        }
    }

    @Override
    public StringBuffer format(Date date, StringBuffer buffer, FieldPosition field) {
        return mParser.format(date, buffer, field);
    }

    private static SimpleDateFormat mParser;
    @Override
    public Date parse(String string, ParsePosition position) {
        String str = string.split("\\.")[0];

        Date date = null;
        try {
            date = mParser.parse(str);
        } catch (ParseException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        position.setIndex(string.length() - 1);
        return date;
    }

    @Override
    public Object clone() {
        return new JacksonSimpleDateFormat();
    }
}
like image 183
nikib3ro Avatar answered Sep 30 '22 00:09

nikib3ro


I may be wrong on this, as I haven't gotten very far into Android development, but the format you presented:

"/Date(1277931782420)/"

Appears to be Unix epoch time.

If that is the case, you would not want/need to use SimpleDateFormat. Instead, try creating a Long from it and passing to the Date constructor, accounting for whether it is seconds or milliseconds-based epoch value.

Here is a StackOverflow post that provides the code for doing so: https://stackoverflow.com/a/535017/463196

like image 25
Philip Tenn Avatar answered Sep 30 '22 00:09

Philip Tenn