java - 将字符串日期转换为对象会产生无效的时区指示符 '0'

标签 java json gson java.util.date

我有一个 Android 应用程序可以接收来自网络服务的 Json 响应。其中一个响应是一个包含日期的 json 字符串。我以“1476399300000”之类的数字形式获取日期。当我尝试使用 GSON 创建一个对象时,我得到了这个错误:

Failed to parse date ["1476399300000']: Invalid time zone indicator '0' (at offset 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));

将给出以下输出:

Fri Oct 14 01:55:00 EEST 2016
{"date":1476399300000}

请注意,类型适配器配置为覆盖默认的 Gson 日期类型适配器。因此,您可能需要使用更复杂的分析来检测 是否只是 Unix 纪元的 ms。另请注意,您可以使用 JsonDeserializer,但后者以 JSON 树方式工作,而类型适配器以流方式工作,这种方式效率更高一些,可能不会累积中间结果。

编辑:

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

编辑

还有一个更短的解决方案(使用 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();

关于java - 将字符串日期转换为对象会产生无效的时区指示符 '0',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41958062/

相关文章:

java - 使用jdbc时如何调用预先配置的postgres函数?

java - 将 JSON 发布到 Spring MVC Controller 返回 400 错误请求

java - Gradle 依赖排除后依赖仍然在类路径上

android - 在 Fragment android 中实现 AsyncTask

java - 使用gson解析空Json数组

java - 如何继承静态字段并更改它的值?

asp.net-mvc - 如何排除某些公共(public)属性被序列化为 JsonResult?

json - 使用带有 Rspec 的 Sinatra 测试 JSON

base64 字符串的 JSON 模式验证不起作用

android - 将 Gson 数据插入 Android Sqlite