Java Gson到json的转换采用两种日期格式
我的服务器JSON返回两种不同类型的DateFormat。 “mm dd,yyyy”和“mm dd,yyyy HH:mm:ss” 当我使用以下代码转换JSON时,一切正常:Java Gson到json的转换采用两种日期格式,java,gson,Java,Gson,我的服务器JSON返回两种不同类型的DateFormat。 “mm dd,yyyy”和“mm dd,yyyy HH:mm:ss” 当我使用以下代码转换JSON时,一切正常: Gson gson = new GsonBuilder().setDateFormat("MMM dd, yyyy").create(); 但当我想要详细的日期格式并将其更改为此格式时,它抛出异常com.google.gson.JsonSyntaxException:2013年3月21日 Gson gson = new G
Gson gson = new GsonBuilder().setDateFormat("MMM dd, yyyy").create();
但当我想要详细的日期格式并将其更改为此格式时,它抛出异常com.google.gson.JsonSyntaxException:2013年3月21日
Gson gson = new GsonBuilder().setDateFormat("MMM dd, yyyy HH:mm:ss").create();
gson是否有办法处理两种不同的日期格式进行Json转换?自定义反序列化是必要的。一个不错的解决方案是使用ApacheCommonsDateUtil,它可以同时处理多种日期格式。另外,JodaTime API可能有类似的特性。我也面临同样的问题。以下是我通过自定义反序列化的解决方案:
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));
}
}
new GsonBuilder().registerTypeAdapter(Date.class,new DateDeserializer());
私有静态最终字符串[]日期\格式=新字符串[]{
“年月日,yyyy HH:mm:ss”,
“年月日”
};
私有类DateDeserializer实现JsonDeserializer{
@凌驾
公共日期反序列化(JsonElement JsonElement,类型为,
JsonDeserializationContext)抛出JsonParseException{
for(字符串格式:日期格式){
试一试{
返回新的SimpleDataFormat(格式,Locale.US).parse(jsoneElement.getAsString());
}捕获(解析异常){
}
}
抛出新的JsonParseException(“不可解析的日期:\”+jsonElement.getAsString()
+“\”。支持的格式:“+Arrays.toString(日期\格式));
}
}
虽然答案已被接受,但我想分享一个类似但更具扩展性的解决方案。你可以找到那个
DateDeserializer.java
public class DateDeserializer<T extends Date> implements JsonDeserializer<T> {
private static final String TAG = DateDeserializer.class.getSimpleName();
private final SimpleDateFormat mSimpleDateFormat;
private final Class<T> mClazz;
public DateDeserializer(SimpleDateFormat simpleDateFormat, Class<T> clazz) {
mSimpleDateFormat = simpleDateFormat;
mClazz = clazz;
}
@Override
public T deserialize(JsonElement element, Type arg1, JsonDeserializationContext context) throws JsonParseException {
String dateString = element.getAsString();
try {
T date = mClazz.newInstance();
date.setTime(mSimpleDateFormat.parse(dateString).getTime());
return date;
} catch (InstantiationException e) {
throw new JsonParseException(e.getMessage(), e);
} catch (IllegalAccessException e) {
throw new JsonParseException(e.getMessage(), e);
} catch (ParseException e) {
throw new JsonParseException(e.getMessage(), e);
}
}
}
非常好的解决方案,而且绝对更具可扩展性。我非常喜欢这一点,但我想知道SimpleDataFormat和线程安全是否有问题。如果是这样,最简单的方法可能是存储格式字符串,并在每次调用DateDeserializer.deserialize()时创建一个新的SimpleDataFormat?噢,我喜欢这个!这真的很干净,很有魅力,非常感谢!正如@BradTofel提到的,这里确实存在一些线程安全问题,正如我在解析包含大约300个日期的JSON时发现的那样。存储日期格式字符串并为每次(反)序列化创建一个新的
SimpleDateFormat
,解决了这个问题!我在改型中使用过这个代码段,但从未调用重写的方法。但是,当在改造上下文之外(在测试类中)使用它时,它可以正常工作。我仍然对它的改型没有问题感到困惑。有没有一种方法可以在不引发异常的情况下尝试格式化(我认为这对性能来说不是最佳的)?@Ixx最好的选择是找到一种使用一种格式的方法,但如果您需要多种格式,我想您可以订购它们以减少异常的数量。如果这不起作用,您可以尝试使用regex并在之后应用格式,但您需要测量regex与exception,以确保值得这么做。
sGson = new GsonBuilder()
.registerTypeAdapter(Event.EventDateTime.class,
new DateDeserializer<Event.EventDateTime>(
Event.EventDateTime.DATE_FORMAT, Event.EventDateTime.class))
.registerTypeAdapter(Event.StartEndDateTime.class,
new DateDeserializer<Event.StartEndDateTime>(
Event.StartEndDateTime.DATE_FORMAT, Event.StartEndDateTime.class))
.registerTypeAdapter(Event.SimpleDate.class,
new DateDeserializer<Event.SimpleDate>(
Event.SimpleDate.DATE_FORMAT, Event.SimpleDate.class))
.create();
public class Event {
@SerializedName("created")
private EventDateTime mCreated;
//@SerializedName("updated")
private EventDateTime mUpdated;
...
@SerializedName("start")
private ConditionalDateTime mStart;
@SerializedName("end")
private ConditionalDateTime mEnd;
public static class ConditionalDateTime {
@SerializedName("dateTime")
private StartEndDateTime mDateTime;
@SerializedName("date")
private SimpleDate mDate;
public SimpleDate getDate() {
return mDate;
}
public StartEndDateTime getDateTime() {
return mDateTime;
}
/**
* If it is an all day event then only date is populated (not DateTime)
* @return
*/
public boolean isAllDayEvent() {
return mDate != null;
}
}
public static class EventDateTime extends Date {
public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
}
public static class StartEndDateTime extends Date {
public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZZZZZ");
}
public static class SimpleDate extends java.util.Date {
public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");
}
}