GSON: Is there a way to return 2 different date formats when sorting
If you define "date" a java.util.Date
where hours, minutes and seconds are zero, and "date with time" a Date
where they are missing. You can do something like this:
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(Date.class, new CustomDateJsonSerializer());
s is CustomDateJsonSerializer
defined as follows:
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);
}
}
source to share
You need to define two different Gorder TypeAdapter implementations.
Then specify in the appropriate Date field in your serialized class which TypeAdapter you want to use.
Use a custom type adapter as shown below with field annotation:
@JsonAdapter(DatePartOnlyGsonAdapter.class)
Date whenever;
public Date getWhenever() {
return whenever;
}
It uses a type of adapter that displays only the format yyyy-MM-dd
, using Java8 LocalDate
formatting when legacy code using the properties java.util.Date
: (
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");
}
}
source to share
Joda-Time | java.time
If you only want a date without any time of day or time zone, then use a different library rather than the java.util.Date and .Calendar classes.
Use either Joda-Time or the java.time package in Java 8 instead. Both offer a class LocalDate
.
Bonus: By default, both use the ISO 8601 standard format for generating and parsing String representations.
source to share