I would like to decode two JSON urls that have different fields for the same item and then combine them into one model object using a struct or class. I am able to work with one JSON url and decode it as needed, but am struggling with adding the second url. I currently have been using structs, but I will be working with large amounts of data, so I understand a class would be better to use here. Any other suggestions would be greatly appreciated. I have searched quite a bit but have been unable to find information that is relevant to this situation in swift 4.
I have below an example that I hope can be manipulated to perform what I'm trying to do. Here we have 1 endpoint that provides state, abbreviation, and region members. The other endpoint provides state, population, and area.
class CollectionViewController: UIViewController {
let urlStates1 = "https://......endpoint1"
let urlStates2 = "https://......endpoint2"
var states = [StatesData]()
override func viewDidLoad() {
super.viewDidLoad()
downloadJSON() {
self.CollectionView.reloadData()
}
}
func downloadJSON(completed:@escaping ()->()){
let url1 = URL(string: urlStates1)
URLSession.shared.dataTask(with: url1!) { (data, response, error) in
if error == nil {
do{
self.states = try JSONDecoder().decode([StatesData].self, from: data!)
DispatchQueue.main.async{
completed()
}
} catch {
print("JSON Error")
}}
}.resume()
}
Here's my struct
struct StatesData : Decodable {
//////Members from URL1///////
var state : String?
var abrev : String?
var region : String?
//////Members specific to URL2///////
var population : Int?
var area : Double?
private enum AttributeKeys: String, CodingKey {
case state = "state"
case abrev = "abrev"
case region = "region"
}
private enum StatisticsKeys: String, CodingKey {
case state = "state"
case population = "population"
case area = "area"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: AttributeKeys.self)
if let stateName = try values.decodeIfPresent(String.self, forKey: .state) {
state = stateName
abrev = try values.decodeIfPresent(String.self, forKey: .abrev)!
region = try values.decodeIfPresent(String.self, forKey: .region)!
} else {
let values = try decoder.container(keyedBy: StatisticsKeys.self)
state = try values.decodeIfPresent(String.self, forKey: .state)!
population = try values.decodeIfPresent(Int.self, forKey: .population)!
area = try values.decodeIfPresent(Double.self, forKey: .area)!
}
}
}
}
Let's say the JSON response for urlStates1 is as follows
[
{
"state": "Connecticut",
"abrev": "CT",
"region": "Northeast"
},
{
"state": "Texas",
"abrev": "TX",
"region": "Southwest"
}
]
And the JSON response for urlStates2 is as follows
[
{
"state": "Connecticut",
"population": 3588000,
"area": 5543.00
},
{
"state": "Texas",
"population": 28300000,
"area": 268597.00
}
]