Using gson dateformat to serialize and deserialize unix-timestamps
Asked Answered
K

2

10

I am using Gson to serialize/deserialize my pojos and currently looking for a clean way to tell Gson to parse/output date attributes as unix-timestamps. Here's my attempt:

Gson gson = new GsonBuilder().setDateFormat("U").create();

Comming from PHP where "U" is the dateformat used to serialize/deserialize date as unix-timestamps, when running my attempt code, I am a RuntimeException:

Unknown pattern character 'U'

I am assuming that Gson uses SimpleDateformat under the hood which doesn't define the letter "U".

I could implement a custom DateTypeAdapter but I am looking for a cleaner way to achieve that. Simply changing the DateFormat would be great.

Katushka answered 27/12, 2016 at 15:42 Comment(0)
K
27

Creating a custom TypeAdapter (UnixTimestampAdapter) was the way to go.

UnixTimestampAdapter

public class UnixTimestampAdapter extends TypeAdapter<Date> {

    @Override
    public void write(JsonWriter out, Date value) throws IOException {
        if (value == null) {
            out.nullValue();
            return;
        }
        out.value(value.getTime() / 1000);
    }

    @Override
    public Date read(JsonReader in) throws IOException {
        if (in.peek() == JsonToken.NULL) {
            in.nextNull();
            return null;
        }
        return new Date(in.nextLong() * 1000);
    }

}

Now, you have to options (depending on your use case):

1 - If you want apply this serialization on all your date fields then register UnixTimestampAdapter upon creating your Gson instance:

Gson gson = new GsonBuilder()
                   .registerTypeAdapter(Date.class, new UnixTimestampAdapter())
                   .create();

2 - Or annotate your date fields with @JsonAdapter (as suggested by @Marcono1234) if you want it applied only to some specific fields.

class Person {
    @JsonAdapter(UnixTimestampAdapter.class)
    private Date birthday;
}
Katushka answered 15/1, 2017 at 23:3 Comment(8)
Hi, your answer resolves your question at github.com/google/gson/issues/987 since ypu have your own solution that is implemented in a true Gson way (not a workaround, that's by design). :) Could you please close the issue? Thanks!Whithersoever
@LyubomyrShaydariv Thanx for reminding me. Your request has been fulfilled. (And you're right sir, that's the way Gson is designed)Katushka
Ah, and one more note: JsonReader.toString returns a human-readable current JsonReader state like JsonReader at line 1 column 1 path $. There's probably a typo, and in.nextString() really does what you need in your code. Or even shorter: new Date(in.nextLong() / 1000).Whithersoever
@LyubomyrShaydariv you're right once again sir. Feel free to make whatever needed correction. This was meant to be "kinda a pseudo-code" to demonstrate how I solved my issue (I'm guilty of not testing it).Katushka
@AnixPasBesoin you've got a mistake in read override. Must be return new Date(in.nextLong() * 1000); The Unix timestamp is in seconds and Date constructor needs milliseconds.Biochemistry
As an alternative to registering the adapter with a GsonBuilder you can instead use @JsonAdapter to change serialization and deserialization only for a specific field.Frazee
@Frazee if you could post your answer with some code it would be helpful to other ppl! (You'll get my upvote)Katushka
@AnisLOUNIS, you can see an example here. Feel free to include parts of it in your answer or just mention that @JsonAdapter placed on a field is an alternative as well. I don't want to create a separate answer to not compete with yours, which answers the question pretty well.Frazee
M
-2

Time stamps are just long's, so you can use that in your POJO. Or use Long to get a null if the field is missing.

class myPOJO {
    Long myDate;
}
Multiplicand answered 27/12, 2016 at 22:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.