使用 Gson 的自定义 JSON 反序列化器

想象一下,你在所有响应中都有一些自定义格式的日期,例如/Date(1465935152)/,并且你希望应用一般规则将所有 Json 日期反序列化为 java Date 实例。在这种情况下,你需要实现自定义 Json 反序列化器。

json 的例子:

{
  "id": 1,
  "created_on": "Date(1465935152)",
  "updated_on": "Date(1465968945)",
  "name": "Oleksandr"
}

假设我们在下面有这个类:

class User {
    @SerializedName("id")
    long id;
    @SerializedName("created_on")
    Date createdOn;
    @SerializedName("updated_on")
    Date updatedOn;
    @SerializedName("name")
    String name;
}

自定义解串器:

class DateDeSerializer implements JsonDeserializer<Date> {
    private static final String DATE_PREFIX = "/Date(";
    private static final String DATE_SUFFIX = ")/";

    @Override
    public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        String dateString = json.getAsString();
        if (dateString.startsWith(DATE_PREFIX) && dateString.endsWith(DATE_SUFFIX)) {
            dateString = dateString.substring(DATE_PREFIX.length(), dateString.length() - DATE_SUFFIX.length());
        } else {
            throw new JsonParseException("Wrong date format: " + dateString);
        }
        return new Date(Long.parseLong(dateString) - TimeZone.getDefault().getRawOffset());
    }
}

用法:

Gson gson = new GsonBuilder()
                .registerTypeAdapter(Date.class, new DateDeSerializer())
                .create();
String json = "....";
User user = gson.fromJson(json, User.class);

使用日期类型序列化和反序列化 Jackson JSON 字符串

例如,这也适用于你希望 Gson Date 转换与 Jackson 兼容的情况。

杰克逊通常将日期序列化为自纪元以来的毫秒,而 Gson 使用像 Aug 31, 2016 10:26:17 这样的可读格式来表示日期。当你尝试反序列化 Jackson 格式的日期时,这会导致 Gson 中的 JsonSyntaxExceptions。

为了避免这种情况,你可以添加自定义序列化程序和自定义反序列化程序:

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();