44

I am in the process of converting from Moshi to kotlinx serialization with Ktor and when I try to make a request to get data I am getting this error

kotlinx.serialization.MissingFieldException: Field 'attachments' is required, but it was missing

which makes sense since this specific response does not contain this field

Response Json

{
    "data": {
        "id": "1299418846990921728",
        "text": "This is a test"
    }
}

BUT my Serialized class has the attachments field as nullable (it is in the response only when it needs to be) so it should just ignore it I thought like it did with Moshi

@Serializable
data class ResponseData(
    val id: Long
    val attachments: Attachments?,
    val author_id: String?,
    val text: String
}

In my Ktor client setup I have it set to ignore unknown keys

private val _client: HttpClient = HttpClient(engine) {
    install(JsonFeature) {
        val json = Json {
            this.isLenient = true
            this.ignoreUnknownKeys = true
        }
        serializer = KotlinxSerializer(json)
    }
}

Why is it still saying that the field is required even though its nullable?

tyczj
  • 71,600
  • 54
  • 194
  • 296

2 Answers2

87

I figured it out, apparently even though you mark something as nullable its still considered required.

For it to truly be optional you need to give it a default value so for example the data class would look like this with the nullables

@Serializable
data class ResponseData(
    val id: Long
    val attachments: Attachments? = null,
    val author_id: String? = null,
    val text: String
}

once you set the value the fields becomes optional and wont throw that exception

tyczj
  • 71,600
  • 54
  • 194
  • 296
  • 6
    I'm still receiving this error and I've tried every suggestion... – Sakiboy Feb 27 '21 at 04:34
  • 2
    @Sakiboy check that your explicitNulls variable is set to *false* and not true. This should resolve the issue of nullable properties not being present in the json, while decoding. – oblakr24 Jul 28 '22 at 16:47
  • @oblakr24 that’s what I ended up needing to do in the set up - initialization. – Sakiboy Jul 29 '22 at 16:03
  • it just worked as explained. No need for further changes. My case was exactly the one explained in the question. Thanks! – nrod Mar 23 '23 at 15:45
  • For kTor 1.6 this solution is working for 2.0 this solution not woking – manivanna perumal Jun 29 '23 at 12:56
27

As of v1.3.0, you can configure the Json feature to treat absent fields as null, with explicitNulls = false

install(JsonFeature) {
    serializer = KotlinxSerializer(
        json = kotlinx.serialization.json.Json {
            explicitNulls = false
        }
    )
}

The documentation for 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 without default 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.

Tim Malseed
  • 6,003
  • 6
  • 48
  • 66