GSON setDateFormat抛出异常时的日期为null

问题描述 投票:3回答:2

我建立了我的GSON实例为:

val DATE_FORMAT_MASK = "yyyy-MM-dd'T'HH:mm:ssZ"

val gson = GsonBuilder()
        .setDateFormat(DATE_FORMAT_MASK)
        .create()

这正常工作,直到我执行空日期的系列化

gson.toJson(null, Date::class.java)

然后我发现了以下情况除外:

java.lang.NullPointerException
    at java.util.Calendar.setTime(Calendar.java:1770)
    at java.text.SimpleDateFormat.format(SimpleDateFormat.java:943)
    at java.text.SimpleDateFormat.format(SimpleDateFormat.java:936)
    at java.text.DateFormat.format(DateFormat.java:345)
    at com.google.gson.DefaultDateTypeAdapter.write(DefaultDateTypeAdapter.java:88)
    at com.google.gson.DefaultDateTypeAdapter.write(DefaultDateTypeAdapter.java:40)
    at com.google.gson.Gson.toJson(Gson.java:669)
    at com.google.gson.Gson.toJson(Gson.java:648)
    at com.google.gson.Gson.toJson(Gson.java:603)

我该如何处理这种情况?

可在GSON库中的缺陷?

date gson kotlin
2个回答
1
投票

如果别人运行到这一点,这个问题存在于GSON的2.8.1版本。无论是要回2.8.0或转发到2.8.2修复该问题。如果你被困在2.8.1,有这个bug报告中详细another workaroundhttps://github.com/google/gson/issues/1096

private Gson getGson() {
  // Trick to get the DefaultDateTypeAdatpter instance
  // Create a first instance a Gson
  Gson gson = new GsonBuilder()
    .setDateFormat(DATE_FORMAT_COMPLETE)
    .create();

  // Get the date adapter
  TypeAdapter<Date> dateTypeAdapter = gson.getAdapter(Date.class);

  // Ensure the DateTypeAdapter is null safe
  TypeAdapter<Date> safeDateTypeAdapter = dateTypeAdapter.nullSafe();

  // Build the definitive safe Gson instance
  return new GsonBuilder()
    .registerTypeAdapter(Date.class, safeDateTypeAdapter)
    .create();
}

3
投票

我真的很吃惊,因为setDateFormat不处理空序列化。我认为你是被迫实施型适配器:

val gson = GsonBuilder()
        //.setDateFormat(DATE_FORMAT_MASK)
        .registerTypeAdapter(Date::class.java, JsonSerializer<Date> { date: Date?, type, context ->
            val parsed = date?.toString(DATE_FORMAT_MASK)
            if(parsed == null) null
            else context?.serialize(parsed)

        })
        .registerTypeAdapter(Date::class.java, JsonDeserializer<Date> { json: JsonElement?, type, context ->
            json?.asString?.toDate(DATE_FORMAT_MASK)
        })
        .create()

toDatetoString是:

fun Date.toString(mask: String): String? {
    try {
        val simpleDateFormat = SimpleDateFormat(mask, Locale.getDefault())
        return simpleDateFormat.format(this)
    } catch (ignored: Exception) {
        return null
    }
}

fun String.toDate(mask: String): Date? {
    return try {
        val simpleDateFormat = SimpleDateFormat(mask, Locale.getDefault())
        simpleDateFormat.parse(this)
    } catch (ignored: Exception) {
        null
    }
}

这包括以下测试:

data class DateWrapper(val date: Date?)

@Test fun date_serialization() {

    val deserializedDate = gson.fromJson("\"2017-10-23T12:48:43+0200\"", Date::class.java)
    assertNotNull(deserializedDate)

    val deserializedNullDate = gson.fromJson("null", Date::class.java)
    assertNull(deserializedNullDate)

    val deserializedNullDate2 = gson.fromJson("", Date::class.java)
    assertNull(deserializedNullDate2)


    val deserializedDateWrapper = gson.fromJson("{date: null}", DateWrapper::class.java)
    assertNull(deserializedDateWrapper.date)

    val deserializedDateWrapper2 = gson.fromJson("{date: \"\"}", DateWrapper::class.java)
    assertNull(deserializedDateWrapper2.date)

    val deserializedDateWrapper3 = gson.fromJson("{}", DateWrapper::class.java)
    assertNull(deserializedDateWrapper3.date)


    val serializedDate = gson.toJson(Date(), Date::class.java)
    assertNotNull(serializedDate)

    val serializedNullDate = gson.toJson(null, Date::class.java)
    assertEquals("null", serializedNullDate)

    val date = Date()
    val serializedDateWrapper = gson.toJson(DateWrapper(date), DateWrapper::class.java)
    assertNotNull(serializedDateWrapper)

    val serializedDateWrapper2 = gson.toJson(DateWrapper(null), DateWrapper::class.java)
    assertNotNull(serializedDateWrapper2)
}
© www.soinside.com 2019 - 2024. All rights reserved.