Après 4 heures d’essais non-stop pour tenter de résoudre le problème, j’ai décidé de demander ici si quelqu'un pouvait m'aider.
Le problème est que mon client Android tente de désérialiser les données reçues d'un serveur et génère l'exception "Unparseable: 1302828677828".
J'aimerais savoir s'il est possible de désérialiser une date au format milliseconde à l'aide de Gson.
Commentaire d'Alfonso:
Finalement j'ai eu la solution:
// Creates the json object which will manage the information received GsonBuilder builder = new GsonBuilder(); // Register an adapter to manage the date types as long values builder.registerTypeAdapter(Date.class, new JsonDeserializer<Date>() { public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { return new Date(json.getAsJsonPrimitive().getAsLong()); } }); Gson gson = builder.create();
J'ai écrit un ImprovedDateTypeAdapter basé sur le DateTypeAdapter GSON par défaut - qui prend en charge le format de dates par défaut et le format timestamp (long).
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
import Java.io.IOException;
import Java.text.DateFormat;
import Java.text.ParseException;
import Java.text.SimpleDateFormat;
import Java.util.Date;
import Java.util.Locale;
import Java.util.TimeZone;
public final class ImprovedDateTypeAdapter extends TypeAdapter<Date> {
public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) {
@SuppressWarnings("unchecked")
TypeAdapter<T> typeAdapter = (TypeAdapter<T>) ((typeToken.getRawType() == Date.class) ? new ImprovedDateTypeAdapter()
: null);
return typeAdapter;
}
};
private final DateFormat enUsFormat;
private final DateFormat localFormat;
private final DateFormat iso8601Format;
public ImprovedDateTypeAdapter() {
this.enUsFormat = DateFormat.getDateTimeInstance(2, 2, Locale.US);
this.localFormat = DateFormat.getDateTimeInstance(2, 2);
this.iso8601Format = buildIso8601Format();
}
private static DateFormat buildIso8601Format() {
DateFormat iso8601Format = new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
iso8601Format.setTimeZone(TimeZone.getTimeZone("UTC"));
return iso8601Format;
}
public Date read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
return deserializeToDate(in.nextString());
}
private synchronized Date deserializeToDate(String json) {
try {
return new Date(Long.parseLong(json));
} catch (Exception e) {
try {
return this.localFormat.parse(json);
} catch (ParseException e1) {
try {
return this.enUsFormat.parse(json);
} catch (ParseException e2) {
try {
return this.iso8601Format.parse(json);
} catch (ParseException e3) {
throw new JsonSyntaxException(json, e3);
}
}
}
}
}
public synchronized void write(JsonWriter out, Date value)
throws IOException {
if (value == null) {
out.nullValue();
return;
}
String dateFormatAsString = this.enUsFormat.format(value);
out.value(dateFormatAsString);
}
}
Pour l'utiliser:
// Creates the json object which will manage the information received
GsonBuilder builder = new GsonBuilder();
// Register an adapter to manage the date types as long values
builder.registerTypeAdapter(Date.class, new ImprovedDateTypeAdapter());
Gson gson = builder.create();
J'ai le même problème lorsque j'ai essayé de désérialiser le champ DateTime avec Rest client of Annotations Android library . Comme solution, j'ai créé un GsonHttpMessageConverter personnalisé.
public class CustomGsonHttpMessageConverter extends GsonHttpMessageConverter {
public CustomGsonHttpMessageConverter() {
// Creates the json object which will manage the information received
GsonBuilder builder = new GsonBuilder();
// Register an adapter to manage the date types as long values
builder.registerTypeAdapter(Date.class, new JsonDeserializer<Date>() {
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
return new Date(json.getAsJsonPrimitive().getAsLong());
}
});
setGson(builder.create());
}
}
et le définir dans le client de repos
@Rest(rootUrl = "http://192.168.1.1:8080", converters = {CustomGsonHttpMessageConverter.class})
public interface RestClient extends RestClientErrorHandling {
...
J'espère que ça vous sera utile
JsonSerializer<Date> serializer= new JsonSerializer<Date>() {
@Override
public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext
context) {
return src == null ? null : new JsonPrimitive(src.getTime());
}
};
JsonDeserializer<Date> deserializer= 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, serializer)
.registerTypeAdapter(Date.class, deserializer).create();