GSON - Format de date

187

J'essaie d'avoir un format de date personnalisé dans la sortie Gson, mais .setDateFormat(DateFormat.FULL)ne semble pas fonctionner et c'est la même chose avec.registerTypeAdapter(Date.class, new DateSerializer()) .

C'est comme si Gson ne se souciait pas de l'objet "Date" et l'imprimait à sa manière.

Comment puis-je changer cela?

Merci

ÉDITER:

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

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

J'utilise toujours java.util.Date; setDateFormat()ne fonctionne pas :(

Stéphane Piette
la source
Avez-vous vérifié que vous importez la classe de date correcte à tous les endroits? Un exemple de code serait également utile.
ML
Que voulez-vous dire par ne fonctionne pas? Que voyez-vous réellement?
AlikElzin-kilaka

Réponses:

306

Il semble que vous deviez définir des formats pour la partie date et heure ou utiliser un formatage basé sur une chaîne. Par exemple:

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

ou en utilisant java.text.DateFormat

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

ou faites-le avec des sérialiseurs:

Je crois que les formateurs ne peuvent pas produire d'horodatages, mais cette paire sérialiseur / désérialiseur semble fonctionner

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

Si vous utilisez Java 8 ou supérieur, vous devez utiliser les sérialiseurs / désérialiseurs ci-dessus comme suit:

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
la source
Ok, cela fonctionne mieux avec votre chemin. Mais comment puis-je afficher les horodatages avec cela?
Stéphane Piette
6
J'utilise Gson 2.2.4 et Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd").create();fonctionne.
Ramsharan
en utilisant Gson 2.2.2 et Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd").create();fonctionne
user2601995
66
Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ").create();

Le format ci-dessus me semble meilleur car il a une précision allant jusqu'à millis.

tj-recess
la source
1
@Abhi - Pourquoi est-il nécessaire de citer «Z»?
tj-recess
1
J'ai essayé sans guillemets et gson a jeté l'exception que la date n'est pas analysable. Cela fonctionne-t-il pour vous sans devis?
Abhi
7
Ce n'est PAS la bonne solution ... le Z signifie le fuseau horaire et il représente le fuseau horaire UTC, si vous le codez en dur comme ça, vous
perdrez
5

Comme ML l'a souligné, JsonSerializer fonctionne ici. Cependant, si vous formatez des entités de base de données, utilisez java.sql.Date pour enregistrer votre sérialiseur. Le désérialiseur n'est pas nécessaire.

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

Ce rapport de bogue peut être lié: http://code.google.com/p/google-gson/issues/detail?id=230 . J'utilise la version 1.7.2 cependant.

Milanka
la source
4

Si vous détestez les classes Inner, en tirant parti de l'interface fonctionnelle, vous pouvez écrire moins de code en Java 8 avec une expression lambda.

JsonDeserializer<Date> dateJsonDeserializer = 
     (json, typeOfT, context) -> json == null ? null : new Date(json.getAsLong());
Gson gson = new GsonBuilder().registerTypeAdapter(Date.class,dateJsonDeserializer).create();
Karthik
la source
Il semble que le contrôle nul puisse être omis (Gson le fait lui-même):Gson gson = new GsonBuilder().registerTypeAdapter(Date.class, (JsonDeserializer) (json, typeOfT, context) -> new Date(json.getAsLong())).create();
gmk57
0

Cela ne fonctionnera pas vraiment du tout. Il n'y a pas de type de date dans JSON. Je recommanderais de sérialiser vers ISO8601 dans les deux sens (pour les formats indépendants et la compatibilité JS). Considérez que vous devez savoir quels champs contiennent des dates.

Michael-O
la source
0

Vous pouvez spécifier votre format Gson gson = builder.setDateFormat("yyyy-MM-dd").create(); dans cette méthode au lieu d' yyyy-MM-ddutiliser d'autres formats

 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
la source
0

Ceci est un bug . Actuellement, vous devez également définir un timeStyleou utiliser l'une des alternatives décrites dans les autres réponses.

Marcono1234
la source
0

Je suis sur Gson 2.8.6 et j'ai découvert ce bogue aujourd'hui.

Mon approche permet à tous nos clients existants (mobile / web / etc) de continuer à fonctionner comme ils l'étaient, mais ajoute une certaine manipulation pour ceux qui utilisent des formats 24h et autorise aussi des millis, pour faire bonne mesure.

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

J'ai gardé la même sérialisation car tous les clients comprennent le format de date json standard.

Normalement, je ne pense pas que ce soit une bonne pratique d'utiliser des blocs try / catch, mais cela devrait être un cas assez rare.

Joe Ciaramitaro
la source