I have a standard URL get request that returns a JSON response. The standard JSON response is written something like this
//get request for the user
{
"USER":
{
"NAME":"myName",
"ID":10000
}
}
//get request for the forums
{
"FORUM":[
{
"SORT":1,
"ID":35,
"TITLE":"Feedback",
"SECTION":"secion1"
},
{
"SORT":2,
"ID":92,
"TITLE":"Choosing an ISP",
"SECTION":"secion2"
},
{
"SORT":3,
"ID":100,
"TITLE":"Broadband",
"SECTION":"section2"
},
{
"SORT":4,
"ID":142,
"TITLE":"“NBN”",
"SECTION":"section2"
},
]
}
//get request for news
{"NEWS":
[
{
"DATE":"2018-10-13T03:56:06+1000",
"SOURCE":"smh.com.au",
"BLURB":"Assistant Treasurer Stuart Robert says he has repaid $37,975 of \"excess usage charges\" in home internet bills footed by taxpayers.",
"ID":102347,
"TITLE":"Stuart Robert pays back $38,000 in excessive home internet charges"
},
{
"DATE":"2018-10-12T18:00:38+1000",
"SOURCE":"itwire.com",
"BLURB":"The CVC costs set by the NBN Co make it very difficult for ISPs to offer gigabit connections to more than a select band of customers who are willing to sign up in numbers and pay slightly more than other speed tiers, according to one ISP who caters to this type of consumer.",
"ID":102343,
"TITLE":"NBN gigabit connections will remain mostly a pipe dream"},
{
"DATE":"2018-10-12T09:48:43+1000",
"SOURCE":"computerworld.com.au",
"BLURB":"The Department of Home Affairs has rejects calls to include independent judicial oversight of the decision to issue Technical Assistance Notices and Technical Capability Notices as part of proposed legislation intended to tackle police agencies’ inability to access encrypted communications services.",
"ID":102342,
"TITLE":"Home Affairs rejects calls for additional safeguards in ‘spyware’ law"
},
{
"DATE":"2018-10-11T12:16:05+1000",
"SOURCE":"itnews.com.au",
"BLURB":"NBN Co is hoping to “speed up” building works on the fibre-to-the-curb (FTTC) portion of its network as it tries to make up lost ground.",
"ID":102334,
"TITLE":"NBN Co says fibre-to-the-curb build is more complex that it hoped"
},
]
}
As we can see, there's top level JSON object for each request and some requests may have an array of nested dictionaries and some like the User request don't.
Issue
I've been googling for a few hours now and have come across dynamic keys and here but not quite what I was after. As the type remains the same. I'd like to have some sort of Generic type that is able to be identified during runtime. A simple method would be to do switch/if statements, but I'd like to be able to let this grow/shrink without much maintenance and repeated code - i'd need to repeat t he URLSession block each time I make a different request.
URLSession.shared.dataTask(with: url) { (data, response, err) in
guard let dataStr = data else {
return
}
do {
let json = try JSONSerialization.jsonObject(with: dataStr, options: [.mutableContainers, .allowFragments]) as! [String: Any]
print("json - \(json)")
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
let root = try decoder.decode(RootUser.self, from: dataStr)// **Identify the Type.self during runtime without conditional statements**
print(root)
} catch let jsonErr {
print("error serializing json", jsonErr)
}
}.resume()
URLSession.shared.dataTask(with: url) { (data, response, err) in
//....
let root = try decoder.decode(RootNews.self, from: dataStr)// **Identify the Type.self during runtime without conditional statements**
//...
}.resume()
URLSession.shared.dataTask(with: url) { (data, response, err) in
//....
let root = try decoder.decode(RootForum.self, from: dataStr)// **Identify the Type.self during runtime without conditional statements**
//...
}.resume()
Question
I'm wondering how can I group these requests into a generic approach without using conditionals
Update
I've expanded a little on the accepted answer based on a generic fetch function. By combining my structures (RootUser, RootNews) into one structure
struct Base: Decodable {
let news: [News]?
let user: User?
enum CodingKeys: String, CodingKey {
case news = "NEWS"
case user = "USER"
}
}
Now when I call the fetch function, I only need to modify the URL not the type (RootUser,RootNews or Foo in the accepted answer), it'll be just type Base.