Nach 4 Stunden ununterbrochenem Versuch, das Problem zu lösen, habe ich mich entschlossen, hier zu fragen, ob mir jemand helfen könnte.
Das Problem ist, dass mein Android-Client beim Versuch, die von einem Server empfangenen Daten zu deserialisieren, die Ausnahme "Unparseable: 1302828677828" auslöst.
Ich würde gerne wissen, ob es möglich ist, ein Datum im Millisekundenformat mit Gson zu deserialisieren.
long
und dann programmgesteuertlong
in aDate
in Ihrem Code konvertieren ?Antworten:
Alfonsos Kommentar:
quelle
.getAsJsonPrimitive()
kann weggelassen werden, und mit Java 8 Lambdas ist es noch kürzer:Gson gson = new GsonBuilder().registerTypeAdapter(Date.class, (JsonDeserializer) (json, typeOfT, context) -> new Date(json.getAsLong())).create();
Ich habe einen ImprovedDateTypeAdapter geschrieben der auf dem GSON-Standard-DateTypeAdapter basiert und das Standard-Datumsformat und das Zeitstempelformat (Langformat) unterstützt.
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); } }
Um es zu benutzen:
// 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();
quelle
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();
quelle
Verwenden Sie das folgende Snippet, um Millisekunden während der Verarbeitung von JSON in Datum zu konvertieren.
GsonBuilder gsonBuilder = new GsonBuilder(); // Adapter to convert long values to date types gsonBuilder.registerTypeAdapter(Date.class, new JsonDeserializer<Date>() { public Date deserialize(JsonElement jsonElement, Type typeOfObj, JsonDeserializationContext context) throws JsonParseException { //Converting milliseconds to current Date. (instead of 1970) return new Date(jsonElement.getAsLong() * 1000); } }); Gson gson = gsonBuilder.setPrettyPrinting().create();
quelle
Ich habe das gleiche Problem, als ich versuchte, das DateTime-Feld mit dem Rest-Client der Android-Anmerkungsbibliothek zu deserialisieren . Als Lösung habe ich einen benutzerdefinierten GsonHttpMessageConverter erstellt
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()); } }
und definieren Sie es im Rest Client
@Rest(rootUrl = "http://192.168.1.1:8080", converters = {CustomGsonHttpMessageConverter.class}) public interface RestClient extends RestClientErrorHandling { ...
Ich hoffe es wird hilfreich sein
quelle
Aus irgendeinem Grund hatte ich Kompilierungsfehler in Intellij mit dem obigen Code unter Verwendung einer anonymen Klasse. Ein Lambda arbeitete für mich:
private static Gson buildGson(){ // Deserialize longs as Dates final JsonDeserializer<Date> dateDeserializer = (json, type, context) -> json == null ? null : new Date(json.getAsLong()); return new GsonBuilder().registerTypeAdapter(Date.class, dateDeserializer).create(); }
quelle