Some context: JSONAPI is a standard way of writing JSON envelopes that includes stuff like pagination, linking to related objects and links to previous page, next page etcetera. Some of my calls use it, some of them don't. The ones that do use it should use a special parser for the results while the regular results just use the regular JSONDecoder.
I want to write the following code:
func parse<ResultType>(data: Data,
including includeList: String,
with httpResponse: HTTPURLResponse) throws -> ResultType where ResultType: Decodable {
switch ResultType.self {
case is some JSONAPIResult.Type: // Putting `some` here is not supported in Swift!
return try jsonAPIDecoder.decode(ResultType.self, from: data, includeList: includeList)
default:
return try jsonDecoder.decode(ResultType.self, from: data)
}
}
This doesn't build since we can't use some
here like we can do in return types. Instead I have to specify the T
JSONAPIResult
needs to conform to making this thing too complicated.
To give you a complete picture, this is what JSONAPIResult
looks like:
// using:
struct JSONAPIResult<T: Decodable>: Decodable, JSONAPIMetaContaining {
let data: T
let meta: JSONAPIMeta
}
What I instead ended up doing was:
// Ducktyping it through a protocol, not ideal but JSONAPIResult wants to know about T
switch ResultType.self {
case is JSONAPIMetaContaining.Type:
return try jsonAPIDecoder.decode(ResultType.self, from: data, includeList: includeList)
default:
return try jsonDecoder.decode(ResultType.self, from: data)
}
}
This code is a bit more brittle than I would like it to be since it depends on that protocol not on the actual type I should send to the jsonAPIDecoder
(JSONAPIResult<T: Decodable>
). Is there a way to check that ResultType
is a JSONAPIResult
without dragging it's nested generic T
since I don't care about T
here.