GSON - Formato data


187

Sto cercando di avere un formato data personalizzato nell'output di Gson, ma .setDateFormat(DateFormat.FULL)non sembra funzionare e lo stesso con .registerTypeAdapter(Date.class, new DateSerializer()).

È come se a Gson non importasse l'oggetto "Data" e lo stampasse a modo suo.

Come posso cambiarlo?

Grazie

MODIFICARE:

@Entity
public class AdviceSheet {
  public Date lastModif;
[...]
}

public void method {
   Gson gson = new GsonBuilder().setDateFormat(DateFormat.LONG).create();
   System.out.println(gson.toJson(adviceSheet);
}

Io uso sempre java.util.Date; setDateFormat()non funziona :(


Hai verificato che stai importando la classe di date corretta in tutti i luoghi? Anche un esempio di codice sarebbe utile.
ML

Cosa intendi con non funziona? Cosa vedi veramente?
AlikElzin-Kilaka,

Risposte:


306

Sembra che sia necessario definire i formati sia per la data che per la parte oraria o utilizzare la formattazione basata su stringhe. Per esempio:

Gson gson = new GsonBuilder()
   .setDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz").create();

o usando java.text.DateFormat

Gson gson = new GsonBuilder()
   .setDateFormat(DateFormat.FULL, DateFormat.FULL).create();

o fallo con i serializzatori:

Credo che i formattatori non possano produrre timestamp, ma questa coppia di serializzatori / deserializzatori sembra funzionare

JsonSerializer<Date> ser = new JsonSerializer<Date>() {
  @Override
  public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext 
             context) {
    return src == null ? null : new JsonPrimitive(src.getTime());
  }
};

JsonDeserializer<Date> deser = 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, ser)
   .registerTypeAdapter(Date.class, deser).create();

Se si utilizza Java 8 o versioni successive, utilizzare i serializzatori / deserializzatori sopra indicati in questo modo:

JsonSerializer<Date> ser = (src, typeOfSrc, context) -> src == null ? null
            : new JsonPrimitive(src.getTime());

JsonDeserializer<Date> deser = (jSon, typeOfT, context) -> jSon == null ? null : new Date(jSon.getAsLong());

Ok funziona meglio con la tua strada. Ma come posso visualizzare i timestamp con questo?
Stéphane Piette,

6
Sto usando Gson 2.2.4 e Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd").create();funziona.
Ramsharan,

usando Gson 2.2.2 e Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd").create();funziona
user2601995

66
Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ").create();

Il formato sopra mi sembra migliore in quanto ha precisione fino a millis.


1
@Abhi - Perché è necessario citare "Z"?
tj-recess

1
Ho provato senza virgolette e gson ha lanciato l'eccezione che la data non è analizzabile. Funziona per te senza virgolette?
Abhi,

7
Questa NON è la soluzione giusta .. la Z significa fuso orario e rappresenta il fuso orario UTC, se lo codifichi in questo modo
perderai

5

Come ha sottolineato ML, JsonSerializer lavora qui. Tuttavia, se si stanno formattando entità di database, utilizzare java.sql.Date per registrare il serializzatore. Deserializer non è necessario.

Gson gson = new GsonBuilder()
   .registerTypeAdapter(java.sql.Date.class, ser).create();

Questa segnalazione di bug potrebbe essere correlata: http://code.google.com/p/google-gson/issues/detail?id=230 . Uso però la versione 1.7.2.


4

Nel caso in cui odi le classi interne, sfruttando l'interfaccia funzionale puoi scrivere meno codice in Java 8 con un'espressione lambda.

JsonDeserializer<Date> dateJsonDeserializer = 
     (json, typeOfT, context) -> json == null ? null : new Date(json.getAsLong());
Gson gson = new GsonBuilder().registerTypeAdapter(Date.class,dateJsonDeserializer).create();

Sembra che il controllo null possa essere omesso (Gson lo fa da solo):Gson gson = new GsonBuilder().registerTypeAdapter(Date.class, (JsonDeserializer) (json, typeOfT, context) -> new Date(json.getAsLong())).create();
gmk57

0

Questo non funzionerà affatto. Non esiste un tipo di data in JSON. Consiglierei di serializzare su ISO8601 avanti e indietro (per formato agnostico e compatibilità JS). Considera che devi sapere quali campi contengono date.


0

È possibile specificare il formato Gson gson = builder.setDateFormat("yyyy-MM-dd").create(); in questo metodo anziché yyyy-MM-ddutilizzare altri formati

 GsonBuilder builder = new GsonBuilder();
                        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.setDateFormat("yyyy-MM-dd").create();

0

Si tratta di un bug . Attualmente devi anche impostare un timeStyleo utilizzare una delle alternative descritte nelle altre risposte.


0

Sono su Gson 2.8.6 e ho scoperto questo bug oggi.

Il mio approccio consente a tutti i nostri clienti esistenti (mobile / web / ecc.) Di continuare a funzionare così com'erano, ma aggiunge un po 'di gestione per coloro che utilizzano i formati 24 ore e consente anche i millis, per una buona misura.

Gson rawGson = new Gson();
SimpleDateFormat fmt = new SimpleDateFormat("MMM d, yyyy HH:mm:ss")
private class DateDeserializer implements JsonDeserializer<Date> {
    @Override
    public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
            throws JsonParseException {
        try {
            return new rawGson.fromJson(json, Date.class);
        } catch (JsonSyntaxException e) {}
        String timeString = json.getAsString();
        log.warning("Standard date deserialization didn't work:" + timeString);
        try {
            return fmt.parse(timeString);
        } catch (ParseException e) {}
        log.warning("Parsing as json 24 didn't work:" + timeString);
        return new Date(json.getAsLong());
    }
}

Gson gson = new GsonBuilder()
    .registerTypeAdapter(Date.class, new DateDeserializer())
    .create();

Ho mantenuto la serializzazione uguale a quella di tutti i client che comprendono il formato di data json standard.

Di solito, non credo sia una buona pratica usare i blocchi try / catch, ma questo dovrebbe essere un caso abbastanza raro.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.