All my JSON responses follow the same structure:
"success": <http code>,
"data": [
]
Where the data
sent back can vary. Sometimes it can contain User
s, sometimes Comment
s, etc. So I want to create a Codable struct
that is flexible to handle the various types of objects being sent back in the data
array.
Here is my current struct
:
struct BasicResponse: Codable {
let success: Int
let data: [User]
}
As you can see, it currently only handles User
data being sent back.
Then, I read the JSON data like this (through Alamofire/Moya):
var users = [User]()
let results = try JSONDecoder().decode(BasicResponse.self, from: response.data)
self.users.append(contentsOf: results.data)
How can I change my struct
file to be more flexible, and how would I then cast the JSON response to the desired object?
So, without going through a lot of design cycles and straight off the top my head, I'd consider trying Swift's generic support, for example...
struct BasicResponse<DataType>: Codable where DataType: Codable {
let success: Int
let data: [DataType]
}
Then you just need to define the implementation of DataType
s you want to use
struct User: Codable {
var name: String
}
And decode it...
let decoder = JSONDecoder()
let response = try decoder.decode(BasicResponse<User>.self, from: data)
print(response.data[0].name)
Now, I just threw this into a Playground and tested it with some basic data...
struct User: Codable {
var name: String
}
struct BasicResponse<T>: Codable where T: Codable {
let success: Int
let data: [T]
}
let data = "{\"success\": 200, \"data\": [ { \"name\":\"hello\" }]}".data(using: .utf8)!
let decoder = JSONDecoder()
do {
let response = try decoder.decode(BasicResponse<User>.self, from: data)
response.data[0].name
} catch let error {
print(error)
}
You might need to "massage" the design to better meet your needs, but it might give you a place to start