当date为null时,Gson setDateFormat会出现异常

时间:2017-10-23 11:25:04

标签: date gson kotlin

我已将我的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库中的一个错误?

2 个答案:

答案 0 :(得分: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)
}

答案 1 :(得分:1)

如果其他任何人遇到此问题,则Gson 2.8.1版中存在此问题。回到2.8.0或前进到2.8.2都可以解决此问题。如果您坚持使用2.8.1,此错误报告中将详细介绍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();
}