Reputation: 1044
So I've been using Swift 4's new Decodable protocol and it's been great, but now I've come across an instance that I can't find an answer. I'm trying to use decodable to parse the Reddit Comments API response. Here is a quick example. (Note this isn't the full response, just something quick for example)
Here is a quick example of my problem. If you look at the "data" key inside of "children" the dictionaries contain different data. Is there a way to have two different JSON objects in the children
array depending on what contents they have or based on their position in the array?
[{
"kind": "Listing",
"data": {
"modhash": "kskppiefdzafc020177a3995ccd7f13b4ba0a8ca70e691a510",
"whitelist_status": "all_ads",
"children": [{
"kind": "t3",
"data": {
"domain": "i.redd.it",
"approved_at_utc": null,
"mod_reason_by": null,
"selftext_html": "Hello world!!!"
}
}]
}
}, {
"kind": "Listing",
"data": {
"modhash": "kskppiefdzafc020177a3995ccd7f13b4ba0a8ca70e691a510",
"whitelist_status": "all_ads",
"children": [{
"kind": "t3",
"data": {
"domain": "i.redd.it",
"approved_at_utc": null,
"author": null,
"body": "Hello world"
}
}]
}
}]
Essentially what I'm curious is possible is this....
public struct CommentRoot: Decodable {
struct Datafield: Decodable {
let modhash: String
let whitelist_status: String
let children: [Comment]? // <------ Can be 1 of 2 types of comment that vary.
let after: String?
let before: String?
}
let data: Datafield
let kind: String
}
Upvotes: 2
Views: 522
Reputation: 1212
I hop it will help you
import Foundation
struct Children : Decodable {
let data : DataInfo?
let kind : String?
enum CodingKeys: String, CodingKey {
case data
case kind = "kind"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
data = try DataInfo(from: decoder)
kind = try values.decodeIfPresent(String.self, forKey: .kind)
}
}
struct DataInfo : Decodable {
let approvedAtUtc : String?
let author : String?
let body : String?
let domain : String?
let children : [Children]?
let modhash : String?
let whitelistStatus : String?
enum CodingKeys: String, CodingKey {
case approvedAtUtc = "approved_at_utc"
case author = "author"
case body = "body"
case domain = "domain"
case children = "children"
case modhash = "modhash"
case whitelistStatus = "whitelist_status"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
approvedAtUtc = try values.decodeIfPresent(String.self, forKey: .approvedAtUtc)
author = try values.decodeIfPresent(String.self, forKey: .author)
body = try values.decodeIfPresent(String.self, forKey: .body)
domain = try values.decodeIfPresent(String.self, forKey: .domain)
children = try values.decodeIfPresent([Children].self, forKey: .children)
modhash = try values.decodeIfPresent(String.self, forKey: .modhash)
whitelistStatus = try values.decodeIfPresent(String.self, forKey: .whitelistStatus)
}
}
Upvotes: 1