explicitNulls

Specifies whether null values should be encoded for nullable properties and must be present in JSON object during decoding.

When this flag is disabled properties with null values are not encoded; during decoding, the absence of a field value is treated as null for nullable properties without a default value.

true by default.

It is possible to make decoder treat some invalid input data as the missing field to enhance the functionality of this flag. See coerceInputValues documentation for details.

Example of usage:

@Serializable
data class Project(val name: String, val description: String?)
val implicitNulls = Json { explicitNulls = false }

// Encoding
// Prints '{"name":"unknown","description":null}'. null is explicit
println(Json.encodeToString(Project("unknown", null)))
// Prints '{"name":"unknown"}', null is omitted
println(implicitNulls.encodeToString(Project("unknown", null)))

// Decoding
// Prints Project(name=unknown, description=null)
println(implicitNulls.decodeFromString<Project>("""{"name":"unknown"}"""))
// Fails with "MissingFieldException: Field 'description' is required"
Json.decodeFromString<Project>("""{"name":"unknown"}""")

Exercise extra caution if you want to use this flag and have non-typical classes with properties that are nullable, but have default value that is not null. In that case, encoding and decoding will not be symmetrical if null is omitted from the output. Example of such a pitfall:

@Serializable
data class Example(val nullable: String? = "non-null default")

val json = Json { explicitNulls = false }

val original = Example(null)
val s = json.encodeToString(original)
// prints "{}" because of explicitNulls flag
println(s)
val decoded = json.decodeFromString<Example>(s)
// Prints "non-null default" because default value is inserted since `nullable` field is missing in the input
println(decoded.nullable)
println(decoded != original) // true