GSON - Date format
It seems that you need to define formats for both date and time part or use String-based formatting. For example:
Gson gson = new GsonBuilder()
.setDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz").create();
or using java.text.DateFormat
Gson gson = new GsonBuilder()
.setDateFormat(DateFormat.FULL, DateFormat.FULL).create();
or do it with serializers:
I believe that formatters cannot produce timestamps, but this serializer/deserializer-pair seems to work
JsonSerializer<Date> ser = new JsonSerializer<Date>() {
@Override
public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext
context) {
return src == null ? null : new JsonPrimitive(src.getTime());
}
};
JsonDeserializer<Date> deser = new JsonDeserializer<Date>() {
@Override
public Date deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context) throws JsonParseException {
return json == null ? null : new Date(json.getAsLong());
}
};
Gson gson = new GsonBuilder()
.registerTypeAdapter(Date.class, ser)
.registerTypeAdapter(Date.class, deser).create();
If using Java 8 or above you should use the above serializers/deserializers like so:
JsonSerializer<Date> ser = (src, typeOfSrc, context) -> src == null ? null
: new JsonPrimitive(src.getTime());
JsonDeserializer<Date> deser = (jSon, typeOfT, context) -> jSon == null ? null : new Date(jSon.getAsLong());
GSON to JSON conversion - long format and simple date format yyyy-MM-dd'T'HH:mm'Z'
Please try following code:
public class Main {
static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm'Z'";
static final Calendar calendar = Calendar.getInstance();
static class LongUtil {
static boolean isLong(String longValue) {
try {
Long.parseLong(longValue);
return true;
} catch (RuntimeException e) {
return false;
}
}
}
static class DateDeserializer implements JsonDeserializer<Date> {
final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATE_FORMAT);
@Override
public Date deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
System.out.println(type.getTypeName());
System.out.println(jsonElement.getAsJsonPrimitive());
if (jsonElement.getAsJsonPrimitive() != null) {
final String expectedDateValue = jsonElement.getAsJsonPrimitive().getAsString();
if (LongUtil.isLong(expectedDateValue)) {
System.out.println("It is long value hence parsing it to long");
calendar.setTimeInMillis(Long.parseLong(expectedDateValue));
return calendar.getTime();
} else {
System.out.println("It is dateformat value hence parsing it to dateformat");
try {
return simpleDateFormat.parse(expectedDateValue);
} catch (ParseException e) {
throw new JsonParseException("Invalud dateFormat while parsing");
}
}
} else {
throw new JsonParseException("JSOn Premitive Exception null");
}
}
}
public static void main(String[] args) throws IOException {
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(Date.class, new DateDeserializer());
Gson gson = builder.create();
Type userListType = new TypeToken<ArrayList<Wrapper>>() {
}.getType();
File file = new File("response.json");
System.out.println("file exists : " + file.exists());
JsonReader jsonReader = new JsonReader(new FileReader(file));
List<Wrapper> wrapper = gson.fromJson(jsonReader, userListType);
System.out.println(wrapper);
}
class Wrapper {
User instance;
@Override
public String toString() {
return "Wrapper{" +
"instance=" + instance +
'}';
}
}
class User {
Location location;
Date timeAtLocation;
@Override
public String toString() {
return "User{" +
"location=" + location +
", timeAtLocation='" + timeAtLocation + '\'' +
'}';
}
}
class Location {
String lat;
String lon;
Date timestamp;
@Override
public String toString() {
return "Location{" +
"lat='" + lat + '\'' +
", lon='" + lon + '\'' +
", timestamp='" + timestamp + '\'' +
'}';
}
}
}
Explaination:
While deserializing
i am checking if the input string is either in dateformat
or in long
and based on that I create the calendar instance, then i set long and finally get date object date otherwise just use the string and format it based on date formatter.
Output:
file exists : true
It is long value hence parsing it to long
It is dateformat value hence parsing it to dateformat
It is long value hence parsing it to long
It is dateformat value hence parsing it to dateformat
[Wrapper{instance=User{location=Location{lat='31.522291', lon='-96.532816', timestamp='Fri May 01 13:49:08 IST 2020'}, timeAtLocation='Thu Apr 23 04:59:00 IST 2020'}}, Wrapper{instance=User{location=Location{lat='31.522291', lon='-96.532816', timestamp='Fri Jan 24 10:12:00 IST 2025'}, timeAtLocation='Mon Dec 23 04:59:00 IST 2019'}}]
GSON: Is there any way to return 2 different date formats while marshalling
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);
}
}
Gson to json conversion with two DateFormat
I was facing the same issue. Here is my solution via custom deserialization:
new GsonBuilder().registerTypeAdapter(Date.class, new DateDeserializer());
private static final String[] DATE_FORMATS = new String[] {
"MMM dd, yyyy HH:mm:ss",
"MMM dd, yyyy"
};
private class DateDeserializer implements JsonDeserializer<Date> {
@Override
public Date deserialize(JsonElement jsonElement, Type typeOF,
JsonDeserializationContext context) throws JsonParseException {
for (String format : DATE_FORMATS) {
try {
return new SimpleDateFormat(format, Locale.US).parse(jsonElement.getAsString());
} catch (ParseException e) {
}
}
throw new JsonParseException("Unparseable date: \"" + jsonElement.getAsString()
+ "\". Supported formats: " + Arrays.toString(DATE_FORMATS));
}
}
Related Topics
Specifying Java Version in Maven - Differences Between Properties and Compiler Plugin
When to Use Wrapper Class and Primitive Type
How to Replace the Awt Eventqueue with Own Implementation
Multi-Project Test Dependencies with Gradle
How to Set Java_Home Environment Variable on MAC Os X 10.9
Jre 1.7 - Java Version - Returns: Java/Lang/Noclassdeffounderror: Java/Lang/Object
Get Variable by Name from a String
How to Remove Entity with Manytomany Relationship in JPA (And Corresponding Join Table Rows)
Using Mockito with Multiple Calls to the Same Method with the Same Arguments
How to Exclude All Instances of a Transitive Dependency When Using Gradle
Java Error: Only a Type Can Be Imported. Xyz Resolves to a Package
Can a Java File Have More Than One Class
How Do Hashcode() and Identityhashcode() Work at the Back End