Search code examples
javajsonkotlinserializationgson

Skip serializing GSON field in generics based on value


We have the need to distinguish between an optional fields vs. nullable fields (i.e when a field is present, that it could be nullable) when serializing Kotlin data classes to JSON using GSON.

The initial thought was to model the optional field as a generic:

class Optional<T>(val isPresent: Boolean = false, val value: T) {}

That would permit representing it in the following serializable data class:

data class SimpleRequest (
    val a: Int = 0,
    val b: Optional<String> = Optional<String>(value = "")
    val c: Optional<String> = Optional<String>(value = "")
    val d: Int? = null,
    val e: Optional<Int?> = Optional<Int?>(value = null)
)

That should result in the following serialized variants (with null serialization enabled):

SimpleRequest(c = Optional<String>(true, "Hello"), e = Optional(true, null))
{
   "a": 0,
   "c": "Hello",
   "d": null,
   "e": null
}

Is this possible?


Solution

  • The custom TypeAdapterFactory for your Optional type would probably be similar to what has been suggested for java.util.Optional.

    To omit the property from JSON even with GsonBuilder.serializeNulls() being enabled, you could choose a similar approach as in this GitHub issue, where the author temporarily calls JsonWriter.setSerializeNulls(false) if the value is null before restoring the previous setting again. In your case you could do that when isPresent == false.

    If you also want to cover deserialization, then you might have to switch to another JSON library because...

    • Gson's main focus is on Java, and it does not support Kotlin that well, see this issue about default values and null handling
    • Gson currently does not allow to handle missing field values (GitHub issue), so you would have to make sure a proper default value is set