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