GSON - Datumsformat

186

Ich versuche, ein benutzerdefiniertes Datumsformat in der Gson-Ausgabe zu haben, aber es .setDateFormat(DateFormat.FULL)scheint nicht zu funktionieren und es ist dasselbe mit .registerTypeAdapter(Date.class, new DateSerializer()).

Es ist, als ob Gson sich nicht um das Objekt "Datum" kümmert und es auf seine Weise druckt.

Wie kann ich das ändern?

Vielen Dank

BEARBEITEN:

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

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

Ich benutze immer java.util.Date; setDateFormat()funktioniert nicht :(

Stéphane Piette
quelle
Haben Sie überprüft, ob Sie an allen Stellen die richtige Datumsklasse importieren? Auch ein Codebeispiel wäre hilfreich.
ML
Was meinst du mit funktioniert nicht? Was siehst du eigentlich?
AlikElzin-Kilaka

Antworten:

305

Es scheint, dass Sie Formate für Datum und Uhrzeit definieren oder eine stringbasierte Formatierung verwenden müssen. Beispielsweise:

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

oder mit java.text.DateFormat

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

oder mach es mit Serialisierern:

Ich glaube, dass Formatierer keine Zeitstempel erzeugen können, aber dieses Serializer / Deserializer-Paar scheint zu funktionieren

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

Wenn Sie Java 8 oder höher verwenden, sollten Sie die oben genannten Serializer / Deserializer wie folgt verwenden:

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());
ML
quelle
Ok, es funktioniert besser mit deinem Weg. Aber wie kann ich damit Zeitstempel anzeigen?
Stéphane Piette
6
Ich benutze Gson 2.2.4 und Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd").create();funktioniert.
Ramsharan
mit Gson 2.2.2 und Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd").create();funktioniert
user2601995
66
Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ").create();

Das obige Format scheint mir besser zu sein, da es eine Präzision von bis zu Millis aufweist.

tj-Pause
quelle
1
@Abhi - Warum ist es notwendig, 'Z' zu zitieren?
tj-Pause
1
Ich habe es ohne Anführungszeichen versucht und gson warf die Ausnahme, dass das Datum nicht analysierbar ist. Funktioniert es bei Ihnen ohne Anführungszeichen?
Abhi
7
Dies ist NICHT die richtige Lösung. Das Z bedeutet Zeitzone und stellt die UTC-Zeitzone dar. Wenn Sie es so fest
codieren,
5

Wie ML betonte, arbeitet JsonSerializer hier. Wenn Sie jedoch Datenbankentitäten formatieren, registrieren Sie Ihren Serializer mit java.sql.Date. Deserializer wird nicht benötigt.

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

Dieser Fehlerbericht könnte verwandt sein: http://code.google.com/p/google-gson/issues/detail?id=230 . Ich benutze allerdings Version 1.7.2.

Milanka
quelle
4

Wenn Sie innere Klassen hassen, können Sie durch die Nutzung der funktionalen Schnittstelle weniger Code in Java 8 mit einem Lambda-Ausdruck schreiben .

JsonDeserializer<Date> dateJsonDeserializer = 
     (json, typeOfT, context) -> json == null ? null : new Date(json.getAsLong());
Gson gson = new GsonBuilder().registerTypeAdapter(Date.class,dateJsonDeserializer).create();
Karthik
quelle
Es scheint, dass die Nullprüfung weggelassen werden kann (Gson macht es selbst):Gson gson = new GsonBuilder().registerTypeAdapter(Date.class, (JsonDeserializer) (json, typeOfT, context) -> new Date(json.getAsLong())).create();
gmk57
0

Das wird überhaupt nicht funktionieren. In JSON gibt es keinen Datumstyp. Ich würde empfehlen, hin und her auf ISO8601 zu serialisieren (für Formatunabhängigkeit und JS-Kompatibilität). Beachten Sie, dass Sie wissen müssen, welche Felder Datumsangaben enthalten.

Michael-O
quelle
0

Sie können Ihr Format Gson gson = builder.setDateFormat("yyyy-MM-dd").create(); in dieser Methode angeben , anstatt yyyy-MM-ddandere Formate zu verwenden

 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();
Abhijit Chakra
quelle
0

Dies ist ein Fehler . Derzeit müssen Sie entweder auch eine festlegen timeStyleoder eine der in den anderen Antworten beschriebenen Alternativen verwenden.

Marcono1234
quelle
0

Ich bin auf Gson 2.8.6 und habe diesen Fehler heute entdeckt.

Mein Ansatz ermöglicht es allen bestehenden Kunden (Mobile / Web / etc), weiterhin so zu funktionieren, wie sie waren, fügt jedoch eine gewisse Handhabung für diejenigen hinzu, die 24-Stunden-Formate verwenden, und ermöglicht auch Millis.

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

Ich habe die Serialisierung beibehalten, da alle Clients das Standard-JSON-Datumsformat verstehen.

Normalerweise halte ich es nicht für eine gute Praxis, Try / Catch-Blöcke zu verwenden, aber dies sollte ein ziemlich seltener Fall sein.

Joe Ciaramitaro
quelle