我有一个类似于Aleksey的解决方案,但可以应用于任何类中的一个或多个字段(Kotlin示例):
创建一个新的注释,用于表示应将其序列化为null的字段:
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FIELD)
annotation class SerializeNull
创建一个TypeAdapterFactory,它检查一个类是否有用这个注解标注的字段,并在写入对象时从JsonTree中删除那些为null且没有用该注解标注的字段。
class SerializableAsNullConverter : TypeAdapterFactory {
override fun <T : Any?> create(gson: Gson, type: TypeToken<T>): TypeAdapter<T>? {
fun Field.serializedName() = declaredAnnotations
.filterIsInstance<SerializedName>()
.firstOrNull()?.value ?: name
val declaredFields = type.rawType.declaredFields
val nullableFieldNames = declaredFields
.filter { it.declaredAnnotations.filterIsInstance<SerializeNull>().isNotEmpty() }
.map { it.serializedName() }
val nonNullableFields = declaredFields.map { it.serializedName() } - nullableFieldNames
return if (nullableFieldNames.isEmpty()) {
null
} else object : TypeAdapter<T>() {
private val delegateAdapter = gson.getDelegateAdapter(this@SerializableAsNullConverter, type)
private val elementAdapter = gson.getAdapter(JsonElement::class.java)
override fun write(writer: JsonWriter, value: T?) {
val jsonObject = delegateAdapter.toJsonTree(value).asJsonObject
nonNullableFields
.filter { jsonObject.get(it) is JsonNull }
.forEach { jsonObject.remove(it) }
val originalSerializeNulls = writer.serializeNulls
writer.serializeNulls = true
elementAdapter.write(writer, jsonObject)
writer.serializeNulls = originalSerializeNulls
}
override fun read(reader: JsonReader): T {
return delegateAdapter.read(reader)
}
}
}
}
使用以下代码将适配器注册到你的Gson实例中:
val builder = GsonBuilder().registerTypeAdapterFactory(SerializableAsNullConverter())
同时,在要置为空的字段上进行注释:
class MyClass(val id: String?, @SerializeNull val name: String?)
序列化结果:
val myClass = MyClass(null, null)
val gson = builder.create()
val json = gson.toJson(myClass)
JSON:
{
"name": null
}
@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
来排除特定字段的空值。 - Davit Mumladze