GSON - format daty

187

Próbuję mieć niestandardowy format daty w danych wyjściowych Gson, ale .setDateFormat(DateFormat.FULL)wydaje się , że nie działa i to samo z .registerTypeAdapter(Date.class, new DateSerializer()).

To tak, jakby Gson nie dbał o obiekt „Data” i drukował go na swój sposób.

Jak mogę to zmienić?

Dzięki

EDYTOWAĆ:

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

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

Zawsze używam java.util.Date; setDateFormat()nie działa :(

Stéphane Piette
źródło
Czy sprawdziłeś, że importujesz prawidłową klasę daty we wszystkich miejscach? Przydałby się również przykładowy kod.
ML
Co masz na myśli mówiąc, że nie działa? Co tak naprawdę widzisz
AlikElzin-kilaka

Odpowiedzi:

306

Wydaje się, że musisz zdefiniować formaty dla części daty i godziny lub użyć formatowania opartego na łańcuchach. Na przykład:

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

lub używając java.text.DateFormat

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

lub zrób to z serializatorami:

Uważam, że formaterery nie mogą tworzyć znaczników czasu, ale ta para serializatora / deserializatora wydaje się działać

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

Jeśli używasz Java 8 lub nowszej wersji, powinieneś użyć powyższych serializatorów / deserializatorów:

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
źródło
Ok, to działa lepiej na twój sposób. Ale jak mogę wyświetlać znaczniki czasu za pomocą tego?
Stéphane Piette
6
Używam Gson 2.2.4 i Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd").create();działa.
Ramsharan,
przy użyciu Gson 2.2.2 i Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd").create();działa
user2601995
66
Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ").create();

Powyższy format wydaje mi się lepszy, ponieważ ma precyzję do milis.

tj-reces
źródło
1
@Abhi - Dlaczego konieczne jest cytowanie „Z”?
tj-reess
1
Próbowałem bez cytatów i gson rzucił wyjątek, że data nie jest analizowalna. Czy to działa dla ciebie bez cytatów?
Abhi
7
To NIE jest właściwe rozwiązanie .. Z oznacza strefę czasową i reprezentuje strefę czasową UTC, jeśli tak ją
zakodujesz
5

Jak wskazał ML, JsonSerializer działa tutaj. Jeśli jednak formatujesz jednostki bazy danych, użyj java.sql.Date, aby zarejestrować swój serializator. Deserializer nie jest potrzebny.

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

Ten raport o błędzie może być powiązany: http://code.google.com/p/google-gson/issues/detail?id=230 . Używam jednak wersji 1.7.2.

Milanka
źródło
4

Jeśli nie znosisz klas wewnętrznych, korzystając z funkcjonalnego interfejsu możesz napisać mniej kodu w Javie 8 z wyrażeniem lambda.

JsonDeserializer<Date> dateJsonDeserializer = 
     (json, typeOfT, context) -> json == null ? null : new Date(json.getAsLong());
Gson gson = new GsonBuilder().registerTypeAdapter(Date.class,dateJsonDeserializer).create();
Karthik
źródło
Wygląda na to, że sprawdzanie wartości zerowej można pominąć (Gson robi to sam):Gson gson = new GsonBuilder().registerTypeAdapter(Date.class, (JsonDeserializer) (json, typeOfT, context) -> new Date(json.getAsLong())).create();
gmk57
0

To tak naprawdę nie zadziała. W JSON nie ma typu daty. Polecam serializację do ISO8601 tam iz powrotem (dla agnostyki formatów i kompatybilności z JS). Weź pod uwagę, że musisz wiedzieć, które pola zawierają daty.

Michael-O
źródło
0

Możesz określić format Gson gson = builder.setDateFormat("yyyy-MM-dd").create(); w tej metodzie zamiast yyyy-MM-ddużywać innych formatów

 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
źródło
0

To jest błąd . Obecnie musisz albo ustawić timeStylealbo, albo użyć jednej z alternatyw opisanych w innych odpowiedziach.

Marcono1234
źródło
0

Korzystam z Gson 2.8.6 i dzisiaj odkryłem ten błąd.

Moje podejście pozwala wszystkim naszym obecnym klientom (mobilnym / internetowym / etc) dalej funkcjonować tak, jak oni, ale dodaje obsługę dla tych, którzy używają formatów 24-godzinnych, a także pozwala milis, na dokładkę.

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

Utrzymałem serializację taką samą, ponieważ wszyscy klienci rozumieją standardowy format daty JSON.

Zwykle nie sądzę, aby dobrą praktyką było używanie bloków try / catch, ale powinien to być dość rzadki przypadek.

Joe Ciaramitaro
źródło