"Nicht analysierbares Datum: 1302828677828" versucht, ein vom Server empfangenes Datum im Millisekundenformat mit Gson zu deserialisieren

80

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.

Alfonso
quelle
Welches Datum / welche Uhrzeit soll dies darstellen?
Squonk
Können Sie es nicht einfach als a analysieren longund dann programmgesteuert longin a Datein Ihrem Code konvertieren ?
aroth
11
Endlich habe ich die Lösung: // Erstellt das JSON-Objekt, das die empfangenen Informationen verwaltet. GsonBuilder builder = new GsonBuilder (); // Registrieren Sie einen Adapter, um die Datumstypen als lange Werte zu verwalten. Builder.registerTypeAdapter (Date.class, new JsonDeserializer <Datum> () {public Date deserialize (JsonElement json, Typ typeOfT, JsonDeserializationContext context) löst JsonParseException aus {return new Date (json .getAsJsonPrimitive (). getAsLong ());}}); Gson gson = builder.create ();
Alfonso

Antworten:

147

Alfonsos Kommentar:

Endlich habe ich die Lösung:

// 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();
Peter O.
quelle
Vielen Dank, dass du mir Zeit gespart hast !!
Chris Sim
Zeitzonenprobleme
ChRoNoN
Danke, das hat mir auch geholfen. Obwohl ich dies für Timestamp verwendet habe.
Feru
Dies funktioniert für jedes Datum, das in Millisenkunden übergeben wird, und nicht für das Übergeben einer Regel für jede Art von analysierten Objekten
Nather Webber,
2
.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();
gmk57
2

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();
Simone Lai
quelle
2
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();
Ahmad Aghazadeh
quelle
1

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();
Chandra Sekhar
quelle
0

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

Vadim Zin4uk
quelle
0

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