Android Deserializer JSON personnalisé avec Gson


Exemple

Imaginez que vous avez toutes les dates dans toutes les réponses dans un format personnalisé, par exemple /Date(1465935152)/ et que vous souhaitez appliquer une règle générale pour désérialiser toutes les dates Json en instances de Date Java. Dans ce cas, vous devez implémenter Json Deserializer personnalisé.

Exemple de json:

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

Supposons que nous ayons cette classe ci-dessous:

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

Désérialiseur personnalisé:

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

Et l'utilisation:

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

Sérialiser et désérialiser les chaînes Jackson JSON avec les types de date

Cela s'applique également au cas où vous souhaitez rendre la conversion de date de Gson compatible avec Jackson, par exemple.

Jackson a l'habitude de sérialiser Date à "millisecondes depuis l'époque" alors que Gson utilise un format lisible comme Aug 31, 2016 10:26:17 pour représenter Date. Cela conduit à JsonSyntaxExceptions dans Gson lorsque vous essayez de désérialiser une date au format Jackson.

Pour contourner ce problème, vous pouvez ajouter un sérialiseur personnalisé et un désérialiseur personnalisé:

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