J'utilise la bibliothèque de conversion pour mes appels REST. La plupart de ce que j'ai fait a été très simple, mais, pour une raison quelconque, j'ai des problèmes pour convertir les chaînes d'horodatage JSON en Java.util.Date
objets. Le JSON qui arrive ressemble à ceci.
{
"date": "2013-07-16",
"created_at": "2013-07-16T22:52:36Z",
}
Comment puis-je dire à Retrofit ou à Gson de convertir ces chaînes en Java.util.Date objects
?
Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss")
.create();
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(API_BASE_URL)
.setConverter(new GsonConverter.create(gson))
.build();
Ou l'équivalent Kotlin:
val gson = GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss").create()
RestAdapter restAdapter = Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.build()
.create(T::class.Java)
Vous pouvez configurer votre analyseur Gson personnalisé pour une mise à niveau. Plus ici: Site Web de rénovation
Examinez la réponse d'Ondreju pour voir comment implémenter cela dans la modernisation 2.
La réponse de @ gderaco a été mise à jour pour la mise à niveau 2.0:
Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss")
.create();
Retrofit retrofitAdapter = new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
Voici comment je l'ai fait:
Créez la classe DateTime prolongeant Date, puis écrivez un désérialiseur personnalisé:
public class DateTime extends Java.util.Date {
public DateTime(long readLong) {
super(readLong);
}
public DateTime(Date date) {
super(date.getTime());
}
}
Passons maintenant à la partie désérialiseur où nous enregistrons les convertisseurs Date et DateTime:
public static Gson gsonWithDate(){
final GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(Date.class, new JsonDeserializer<Date>() {
final DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
@Override
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
try {
return df.parse(json.getAsString());
} catch (final Java.text.ParseException e) {
e.printStackTrace();
return null;
}
}
});
builder.registerTypeAdapter(DateTime.class, new JsonDeserializer<DateTime>() {
final DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Override
public DateTime deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
try {
return new DateTime(df.parse(json.getAsString()));
} catch (final Java.text.ParseException e) {
e.printStackTrace();
return null;
}
}
});
return builder.create();
}
Et lorsque vous créez votre RestAdapter, procédez comme suit:
new RestAdapter.Builder().setConverter(gsonWithDate());
Votre Foo devrait ressembler à ceci:
class Foo {
Date date;
DateTime created_at;
}
Gson ne peut gérer qu'un seul format date/heure (ceux spécifiés dans le générateur) plus l'iso8601 si l'analyse avec le format personnalisé n'est pas possible. Une solution pourrait donc consister à écrire votre désérialiseur personnalisé. Pour résoudre votre problème, j'ai défini:
package stackoverflow.questions.q18473011;
import Java.util.Date;
public class Foo {
Date date;
Date created_at;
public Foo(Date date, Date created_at){
this.date = date;
this.created_at = created_at;
}
@Override
public String toString() {
return "Foo [date=" + date + ", created_at=" + created_at + "]";
}
}
avec ce désérialiseur:
package stackoverflow.questions.q18473011;
import Java.lang.reflect.Type;
import Java.text.*;
import Java.util.Date;
import com.google.gson.*;
public class FooDeserializer implements JsonDeserializer<Foo> {
public Foo deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
String a = json.getAsJsonObject().get("date").getAsString();
String b = json.getAsJsonObject().get("created_at").getAsString();
SimpleDateFormat sdfDate = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat sdfDateWithTime = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
Date date, created;
try {
date = sdfDate.parse(a);
created = sdfDateWithTime.parse(b);
} catch (ParseException e) {
throw new RuntimeException(e);
}
return new Foo(date, created);
}
}
La dernière étape consiste à créer une instance Gson
avec le bon adaptateur:
package stackoverflow.questions.q18473011;
import com.google.gson.*;
public class Question {
/**
* @param args
*/
public static void main(String[] args) {
String s = "{ \"date\": \"2013-07-16\", \"created_at\": \"2013-07-16T22:52:36Z\"}";
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(Foo.class, new FooDeserializer());
Gson gson = builder.create();
Foo myObject = gson.fromJson(s, Foo.class);
System.out.println("Result: "+myObject);
}
}
Mon résultat:
Result: Foo [date=Tue Jul 16 00:00:00 CEST 2013, created_at=Tue Jul 16 22:52:36 CEST 2013]
Littéralement, si vous avez déjà un objet Date avec le nom "created_at" dans la classe que vous créez, c'est très simple:
Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").create();
YourObject parsedObject1 = gson.fromJson(JsonStringYouGotSomehow, YourObject.class);
Et tu as fini. pas de dépassement compliqué nécessaire.
Vous pouvez définir deux nouvelles classes comme ceci:
import Java.util.Date;
public class MyDate extends Date {
}
et
import Java.util.Date;
public class CreatedAtDate extends Date {
}
Votre POJO sera comme ça:
import MyDate;
import CreatedAtDate;
public class Foo {
MyDate date;
CreatedAtDate created_at;
}
Enfin, définissez votre désérialiseur personnalisé:
public class MyDateDeserializer implements JsonDeserializer<Date> {
public static final SimpleDateFormat sServerDateDateFormat = new SimpleDateFormat("yyyy-MM-dd");
@Override
public MyDate deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
if (json != null) {
final String jsonString = json.getAsString();
try {
return (MyDate) sServerDateDateFormat.parse(jsonString);
} catch (ParseException e) {
e.printStackTrace();
}
}
return null;
}
}
et
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(MyDate.class, new MyDateDeserializer());