mannu
mannu

Reputation: 43

GSON: Is there any way to return 2 different date formats while marshalling

GsonBuilder.setDateFormat("yyyy-MM-dd HH:mm:ss") is appending 00:00:00 for date only fields. Is there any way to override this behavior as requirement is to show date only as well as date with time.

Upvotes: 3

Views: 1822

Answers (3)

Adam
Adam

Reputation: 5445

You need to define two different Gson TypeAdapter implementations.

Then specify on the appropriate Date field on your serializable class which TypeAdapter you wish to use.

Use a custom type adapter like below with the field annotation:

@JsonAdapter(DatePartOnlyGsonAdapter.class)
Date whenever; 

public Date getWhenever() {
    return whenever;
}

Here's a type adapter which outputs just the yyyy-MM-dd format, using Java8's LocalDate to do formatting, when you have inherited code using java.util.Date properties :(

import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;

import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Date;

public class DatePartOnlyGsonAdapter extends TypeAdapter<Date> {

    @Override
    public void write(JsonWriter out, Date src) throws IOException {
        if (src == null) {
            out.nullValue();
            return;
        }
        LocalDate d = new java.sql.Date(src.getTime()).toLocalDate();
        out.value(d.format(DateTimeFormatter.ISO_DATE));
    }

    @Override
    public Date read(JsonReader in) throws IOException {
        throw new IllegalStateException("Gson Date reader not implemented");
    }
}

Upvotes: 1

Basil Bourque
Basil Bourque

Reputation: 338775

Joda-Time | java.time

If you want a date only without any time of day or time zone, use another library rather than the java.util.Date and .Calendar classes.

Instead use either Joda-Time or java.time package in Java 8. Both offer a LocalDate class.

Bonus: By default both use the standard ISO 8601 format for generating and parsing String representations.

Upvotes: 0

Xavier Delamotte
Xavier Delamotte

Reputation: 3599

If you define a "date" a java.util.Date where hours, minutes and seconds are equal to zero, and "date with time" a Date where they are not. You coud do something like that:

    GsonBuilder builder = new GsonBuilder();
    builder.registerTypeAdapter(Date.class, new CustomDateJsonSerializer());

with CustomDateJsonSerializer define like this:

public class CustomDateJsonSerializer implements JsonSerializer<Date>, JsonDeserializer<Date> {
    private static final TimeZone UTC_TIME_ZONE = TimeZone.getTimeZone("UTC");
    private static final Pattern DATE_PATTERN = Pattern.compile("\\d{4}-\\d{2}-\\d{2}");
    private static final Pattern DATE_TIME_PATTERN = Pattern.compile("\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}");

    public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        String asString = json.getAsString();
        try {
            if (DATE_PATTERN.matcher(asString).matches()) {
                return getDateFormat().parse(asString);
            } else if (DATE_TIME_PATTERN.matcher(asString).matches()) {
                return getDateTimeFormat().parse(asString);
            } else {
                throw new JsonParseException("Could not parse to date: " + json);
            }
        } catch (ParseException e) {
            throw new JsonParseException("Could not parse to date: " + json, e);
        }
    }

    private static DateFormat getDateFormat() {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("YYYY-MM-dd");
        simpleDateFormat.setTimeZone(UTC_TIME_ZONE);
        return simpleDateFormat;
    }

    private static DateFormat getDateTimeFormat() {
        SimpleDateFormat dateFormat = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss");
        dateFormat.setTimeZone(UTC_TIME_ZONE);
        return dateFormat;
    }

    public JsonElement serialize(Date date, Type typeOfSrc, JsonSerializationContext context) {
        Calendar calendar = Calendar.getInstance(UTC_TIME_ZONE);
        calendar.setTime(date);
        int hours = calendar.get(Calendar.HOUR);
        int minutes = calendar.get(Calendar.MINUTE);
        int seconds = calendar.get(Calendar.SECOND);
        String dateFormatted;
        if (hours == 0 && minutes == 0 && seconds == 0) {
            dateFormatted = getDateFormat().format(date);
        } else {
            dateFormatted = getDateTimeFormat().format(date);
        }
        return new JsonPrimitive(dateFormatted);
    }
}

Upvotes: 2

Related Questions