„Data nierozdzielna: 1302828677828” próba deserializacji z Gson data w formacie milisekund odebrana z serwera


80

Po 4 godzinach nieustannych prób rozwiązania problemu postanowiłem zapytać tutaj, czy ktoś mógłby mi pomóc.

Problem polega na tym, że mój klient z Androidem, próbując deserializować dane odebrane z serwera, zgłasza wyjątek „Unparseable: 1302828677828”.

Chciałbym wiedzieć, czy można deserializować datę w formacie milisekund za pomocą Gson.


Jaką datę / godzinę ma to oznaczać?
Squonk

Czy nie możesz po prostu przeanalizować go jako a long, a następnie programowo przekonwertować go longna a Datew swoim kodzie?
aroth

11
Wreszcie znalazłem rozwiązanie: // Tworzy obiekt json, który będzie zarządzał otrzymanymi informacjami GsonBuilder builder = new GsonBuilder (); // Zarejestruj adapter, aby zarządzać typami dat jako długie wartości 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 ();
Alfonso,

Odpowiedzi:


147

Komentarz Alfonso:

Wreszcie znalazłem rozwiązanie:

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

Dziękuję bardzo, że zaoszczędziłeś mój czas !!
Chris Sim

problemy ze
strefą

Dzięki temu również mi pomogło. Chociaż użyłem tego dla Timestamp.
Feru,

to działa dla każdej daty, która jest przekazywana w milisekundach, a nie do przekazywania reguły dla każdego rodzaju analizowanych obiektów
Nather Webber

2
.getAsJsonPrimitive()można pominąć, aw przypadku Gson gson = new GsonBuilder().registerTypeAdapter(Date.class, (JsonDeserializer) (json, typeOfT, context) -> new Date(json.getAsLong())).create();
lambd

2

Napisałem ImprovedDateTypeAdapter na podstawie domyślnego DateTypeAdapter GSON, który obsługuje domyślny format dat i format znacznika czasu (długi).

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

Aby z niego skorzystać:

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

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

1

Użyj poniższego fragmentu kodu, aby przekonwertować milisekundy na Date podczas przetwarzania JSON.

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

0

Mam ten sam problem, gdy próbowałem deserializowania DateTime pole z Rest klienta z Androidem adnotacje bibliotece. Jako rozwiązanie stworzyłem niestandardowy GsonHttpMessageConverter

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

i zdefiniuj to w rest kliencie

@Rest(rootUrl = "http://192.168.1.1:8080", converters = {CustomGsonHttpMessageConverter.class})
public interface RestClient extends RestClientErrorHandling {
...

Mam nadzieję, że będzie to pomocne


0

Z jakiegoś powodu miałem błędy kompilacji w Intellij z powyższym kodem używającym anonimowej klasy; pracowała dla mnie lambda:

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();
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.