I am currently implementing an API client with Ktor. The API I am requesting does not return a consistent JSON format.
for Example:
sometimes the JSON looks like this:
{
"description": {
"lang": "en",
"value": "an English description..."
},
...
}
and sometimes like this:
{
"description": [
{
"lang": "en",
"value": "an English description..."
},
{
"lang": "fr",
"value": "a French description..."
}
],
...
}
Now my Question:
How can I implement a Custom Kotlinx Deserializer to Decode an Object of T or a List<T> to a List<T>
My classes look like this:
@Serializable
class ResourceResponse(
@SerialName("description")
val descriptions: List<Description>
) {
@Serializable
data class Description(
@SerialName("value")
val value: String,
@SerialName("lang")
val language: String,
)
}
I want that a Json with only one Description-Object will be deserialized to a List with one Object and not specifically for the description, but in general for classes.
I’ve found nothing really helpful in the Web.
4
Answers
After my research, I have now come up with a solution. For this you need a wrapper class. (here GenericResponse). I hope I can help others who have the same problem.
This is the Wrapper-Class
And the Serializer looks like:
My Data-Class look now like:
it should be like that
One solution is to first deserialize it to
JsonElement
, introspect and then decide how to deserialize it further intoResourceResponse
:This solution is definitely not ideal. It may be potentially less performant as we need to deserialize the whole tree into the tree of
JsonElement
objects only to transform it to the final types (although, maybe the library does this internally anyway). It works only for json and it is tricky to use this solution ifResourceResponse
is somewhere deep into the data structure.You can use a JsonContentPolymorphicSerializer to choose a deserializer based on the form of the JSON.
This one should work:
You must also amend your original class to tell it to use this serializer:
Then you will be able to decode JSON objects with the single key "descriptions" using the
ResourceResponse
serializer.For avoidance of doubt, if there are other keys in the JSON (it’s not entirely clear from the question) then those should also be written into
ResourceResponse
definition.