I have called an API to get all holidays in a year, it came out a Json type. But I only can extract it like below (it is one of many elements of "items")
"items": [
{
"kind": "calendar#event",
"etag": "\"3235567993214000\"",
"id": "20200101_1814eggq09ims8ge9pine82pclgn49rj41262u9a00oe83po05002i01",
"status": "confirmed",
"htmlLink": "https://www.google.com/calendar/event?eid=MjAyMDAxMDFfMTgxNGVnZ3EwOWltczhnZTlwaW5lODJwY2xnbjQ5cmo0MTI2MnU5YTAwb2U4M3BvMDUwMDJpMDEgZW4udWsjaG9saWRheUB2",
"created": "2021-04-07T08:26:36.000Z",
"updated": "2021-04-07T08:26:36.607Z",
"summary": "New Year's Day",
"creator": {
"email": "en.uk#holiday@group.v.calendar.google.com",
"displayName": "Holidays in United Kingdom",
"self": true
},
"organizer": {
"email": "en.uk#holiday@group.v.calendar.google.com",
"displayName": "Holidays in United Kingdom",
"self": true
},
"start": {
"date": "2020-01-01"
},
"end": {
"date": "2020-01-02"
},
"transparency": "transparent",
"visibility": "public",
"iCalUID": "20200101_1814eggq09ims8ge9pine82pclgn49rj41262u9a00oe83po05002i01@google.com",
"sequence": 0,
"eventType": "default"
},
{
"kind": "calendar#event",
"etag": "\"3235567993214000\"",
"id": "20200412_1814eggq09ims8gd8lgn6t35e8g56tbechgniag063i0ue048064g0g",
"status": "confirmed",
"htmlLink": "https://www.google.com/calendar/event?eid=MjAyMDA0MTJfMTgxNGVnZ3EwOWltczhnZDhsZ242dDM1ZThnNTZ0YmVjaGduaWFnMDYzaTB1ZTA0ODA2NGcwZyBlbi51ayNob2xpZGF5QHY",
"created": "2021-04-07T08:26:36.000Z",
"updated": "2021-04-07T08:26:36.607Z",
"summary": "Easter Sunday",
"creator": {
"email": "en.uk#holiday@group.v.calendar.google.com",
"displayName": "Holidays in United Kingdom",
"self": true
},
"organizer": {
"email": "en.uk#holiday@group.v.calendar.google.com",
"displayName": "Holidays in United Kingdom",
"self": true
},
"start": {
"date": "2020-04-12"
},
"end": {
"date": "2020-04-13"
},
"transparency": "transparent",
"visibility": "public",
"iCalUID": "20200412_1814eggq09ims8gd8lgn6t35e8g56tbechgniag063i0ue048064g0g@google.com",
"sequence": 0,
"eventType": "default"
}
I try to get the value in key "start" and key "summary" but I can't.
Xcode told me that "items" is a __NSArrayI
type.
What I've tried so far is create a class simple like this (just use to try first, so I didn't make all variable)
class API_Info {
var kind: String?
var etag: String?
var id: String?
var status: String?
var htmlLink: String?
var created: String?
var updated: String?
var summary: String?
init(items: [String:Any]){
self.kind = items["kind"] as? String
self.etag = items["etag"] as? String
self.id = items["id"] as? String
self.status = items["status"] as? String
self.htmlLink = items["htmlLink"] as? String
self.created = items["created"] as? String
self.updated = items["updated"] as? String
self.summary = items["summary"] as? String
}
}
And I parse like this:
guard let items = json!["items"]! as? [API_Info] else{
print("null")
return
}
In this way, else statement was run.
What am I doing wrong, and how can I get the data I want?
Thanks in advance.
Codable
is the solution here. Below is the struct I used rather than your class
struct ApiInfo: Codable {
let kind: String
let etag: String
let id: String
let status: String
let htmlLink: String
let created: Date
let updated: Date
let summary: String
}
Then I created a root type to hold the array
struct Result: Codable {
let items: [ApiInfo]
}
And then the decoding
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(formatter)
do {
let result = try decoder.decode(Result.self, from: data)
print(result.items)
} catch {
print(error)
}
Notice that the data values are decoded to Date
objects.
Optionally you can skip the root type and decode as a dictionary
do {
let items = try decoder.decode([String: [ApiInfo]].self, from: data)
if let values = items["items"] {
print(values)
}
} catch {
print(error)
}