GSON - Format tanggal

187

Saya mencoba memiliki format tanggal khusus dalam keluaran Gson, tetapi .setDateFormat(DateFormat.FULL)sepertinya tidak berfungsi dan sama dengan itu .registerTypeAdapter(Date.class, new DateSerializer()).

Ini seperti Gson tidak peduli dengan objek "Date" dan mencetaknya dengan caranya.

Bagaimana saya bisa mengubahnya?

Terima kasih

EDIT:

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

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

Saya selalu menggunakan java.util.Date; setDateFormat()tidak bekerja :(

Stéphane Piette
sumber
Sudahkah Anda memeriksa bahwa Anda mengimpor kelas-kelas yang benar di semua tempat? Contoh kode juga akan sangat membantu.
ML
Apa yang Anda maksud dengan tidak berhasil? Apa yang sebenarnya kamu lihat?
AlikElzin-kilaka

Jawaban:

306

Tampaknya Anda perlu menentukan format untuk bagian tanggal dan waktu atau menggunakan pemformatan berbasis string. Sebagai contoh:

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

atau menggunakan java.text.DateFormat

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

atau melakukannya dengan serializers:

Saya percaya bahwa pemformat tidak dapat menghasilkan cap waktu, tetapi pasangan seri / deserializer ini tampaknya berfungsi

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

Jika menggunakan Java 8 atau lebih baru Anda harus menggunakan serializers / deserializers di atas seperti:

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
sumber
Ok itu bekerja lebih baik dengan cara Anda. Tetapi bagaimana saya bisa menampilkan cap waktu dengan ini?
Stéphane Piette
6
Saya menggunakan Gson 2.2.4 dan Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd").create();bekerja.
Ramsharan
menggunakan Gson 2.2.2 dan Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd").create();bekerja
user2601995
66
Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ").create();

Format di atas sepertinya lebih baik bagi saya karena memiliki presisi hingga milidetik.

t-reses
sumber
1
@ Abhi - Mengapa mengutip 'Z' perlu?
tj-reses
1
Saya mencoba tanpa tanda kutip dan gson melemparkan Pengecualian bahwa tanggal tersebut tidak dapat diuraikan. Apakah itu bekerja untuk Anda tanpa tanda kutip?
Abhi
7
INI BUKAN solusi yang tepat .. Z berarti zona waktu dan mewakili zona waktu UTC, jika Anda meng-hardcode-nya seperti ini, Anda akan kehilangan info itu
Billda
5

Seperti yang ditunjukkan ML, JsonSerializer bekerja di sini. Namun, jika Anda memformat entitas basis data, gunakan java.sql.Date untuk mendaftarkan serializer Anda. Deserializer tidak diperlukan.

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

Laporan bug ini mungkin terkait: http://code.google.com/p/google-gson/issues/detail?id=230 . Saya menggunakan versi 1.7.2.

Milanka
sumber
4

Jika Anda membenci kelas dalam, dengan memanfaatkan antarmuka fungsional, Anda dapat menulis lebih sedikit kode di Java 8 dengan ekspresi lambda.

JsonDeserializer<Date> dateJsonDeserializer = 
     (json, typeOfT, context) -> json == null ? null : new Date(json.getAsLong());
Gson gson = new GsonBuilder().registerTypeAdapter(Date.class,dateJsonDeserializer).create();
Karthik
sumber
Tampaknya cek nol dapat dihilangkan (Gson melakukannya sendiri):Gson gson = new GsonBuilder().registerTypeAdapter(Date.class, (JsonDeserializer) (json, typeOfT, context) -> new Date(json.getAsLong())).create();
gmk57
0

Ini tidak akan berhasil sama sekali. Tidak ada tipe tanggal di JSON. Saya akan merekomendasikan untuk membuat serial ke ISO8601 bolak-balik (untuk format agnostik dan JS compat). Pertimbangkan bahwa Anda harus tahu bidang mana yang berisi tanggal.

Michael-O
sumber
0

Anda dapat menentukan format Gson gson = builder.setDateFormat("yyyy-MM-dd").create(); dalam metode ini alih-alih yyyy-MM-ddmenggunakan format lainnya

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

Ini adalah bug . Saat ini Anda harus menetapkan timeStylejuga atau menggunakan salah satu alternatif yang dijelaskan dalam jawaban lain.

Marcono1234
sumber
0

Saya menggunakan Gson 2.8.6 dan menemukan bug ini hari ini.

Pendekatan saya memungkinkan semua klien kami yang ada (seluler / web / dll) untuk terus berfungsi sebagaimana mestinya, tetapi menambahkan beberapa penanganan bagi mereka yang menggunakan format 24jam dan memungkinkan miliaran juga, untuk ukuran yang baik.

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

Saya tetap membuat serialisasi sama seperti semua klien memahami format tanggal json standar.

Biasanya, saya pikir itu bukan praktik yang baik untuk menggunakan blok coba / tangkap, tetapi ini harus menjadi kasus yang cukup langka.

Joe Ciaramitaro
sumber