将字符串日期转换为对象生成无效的时区指示器'0'



我有一个Android应用程序,它从web服务接收Json响应。其中一个响应是一个包含日期的json字符串。我得到的日期是一个类似"1476399300000"的数字。当我尝试使用GSON创建一个对象时,我会得到以下错误:

无法分析日期["1476399300000']:时区指示符'0'无效(偏移量为0)

双方都在使用java.util.Date

如何解决此问题?

1476399300000看起来像Unix epoch开始时的ms。只需在Gson中添加一个类型适配器:

final class UnixEpochDateTypeAdapter
extends TypeAdapter<Date> {
private static final TypeAdapter<Date> unixEpochDateTypeAdapter = new UnixEpochDateTypeAdapter();
private UnixEpochDateTypeAdapter() {
}
static TypeAdapter<Date> getUnixEpochDateTypeAdapter() {
return unixEpochDateTypeAdapter;
}
@Override
public Date read(final JsonReader in)
throws IOException {
// this is where the conversion is performed
return new Date(in.nextLong());
}
@Override
@SuppressWarnings("resource")
public void write(final JsonWriter out, final Date value)
throws IOException {
// write back if necessary or throw UnsupportedOperationException
out.value(value.getTime());
}
}

配置您的Gson实例:

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

Gson实例和UnixEpochDateTypeAdapter实例一样是线程安全的,并且可以作为一个实例全局存在。示例:

final class Mapping {   
final Date date = null; 
}
final String json = "{"date":1476399300000}";
final Mapping mapping = gson.fromJson(json, Mapping.class);
System.out.println(mapping.date);
System.out.println(gson.toJson(mapping));

将给出以下输出:

2016年10月14日星期五欧洲经济标准时间01:55:00
{"日期":1476399300000}

请注意,类型适配器被配置为覆盖默认的Gson日期类型适配器。因此,您可能需要使用更复杂的分析来检测是否只是Unix时代的毫秒。还要注意,您可以使用JsonDeserializer,但后者以JSON树的方式工作,而类型适配器以流的方式工作——这在一定程度上更高效——可能不会累积中间结果。

编辑:

此外,它看起来可能令人困惑,但Gson可以对基元进行值转换。尽管有效负载有一个字符串值,但JsonReader.nextLong()可以将字符串基元读取为长值。因此,为了不修改JSON文本,UnixEpochDateTypeAdapter.write应该是out.value(String.valueOf(value.getTime()));

编辑

还有一个较短的解决方案(在内存树中使用JSON,而不是数据流),它只是:

final Gson builder = new GsonBuilder()
.registerTypeAdapter(Date.class, new JsonDeserializer<Date>() { 
public Date deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext context) throws JsonParseException {
return new Date(jsonElement.getAsJsonPrimitive().getAsLong()); 
} 
})
.create();

最新更新