Say we’ve got a cursor based paginated API where multiple endpoints can be paginated. The response of such an endpoint is always as follows:
{
"nextCursor": "someString",
"PAYLOAD_KEY": <generic response>
}
So the payload always returns a cursor and the payload key depends on the actual endpoint we use. For example if we have GET /users
it might be users
and the value of the key be an array of objects or we could cal a GET /some-large-object
and the key being item
and the payload be an object.
Bottom line the response is always an object with a cursor and one other key and it’s associated value.
Trying to make this generic in Swift I was thinking of this:
public struct Paginable<Body>: Codable where Body: Codable {
public let body: Body
public let cursor: String?
private enum CodingKeys: String, CodingKey {
case body, cursor
}
}
Now the only issue with this code is that it expects the Body
to be accessible under the "body"
key which isn’t the case.
We could have a struct User: Codable
and the paginable specialized as Paginable<[Users]>
where the API response object would have the key users
for the array.
My question is how can I make this generic Paginable
struct work so that I can specify the JSON payload key from the Body
type?
2
Answers
You can use generic model with type erasing, for example
The simplest solution I can think of is to let the decoded
Body
to give you the decoding key:For example:
Another option is to always take the "other" non-cursor key as the body:
Another possible option is to pass the decoding key directly to
JSONDecoder
insideuserInfo
and then access it insideinit(from:)
. That would give you the biggest flexibility but you would have to specify it always during decoding.