I'm trying to decode a JSON with swift codable but I'm having issues on how to handle the data, especially because the structure is dynamic, so I've used an enum to parse the JSON.
After parsing the data I'm trying to use an array map but gives me errors
Here is a JSON sample (if you need the full version here the URL) :
{
"kind": "Listing",
"data": {
"after": null,
"dist": 1,
"modhash": "",
"geo_filter": "",
"children": [
{
"kind": "t1",
"data": {
"title": "Test",
"score": 88,
"replies": {
"kind": "Listing",
"data": {
"after": null,
"dist": null,
"modhash": "",
"geo_filter": "",
"children": [
{
"kind": "t1",
"data": {
"title": "Test",
"score": 88
}
},
{
"kind": "t1",
"data": {
"title": "post",
"score": 12
}
}
]
}
}
}
}
]
}
}
Here is how I have parsed the JSON
import Foundation
enum DataType : String, Decodable {
case listing = "Listing"
case t1
case t3
case more
}
indirect enum Parse : Decodable {
case listing(Listing)
case t1(Comment)
case t3(Comment)
case more(More)
enum CodingKeys : String, CodingKey {
case kind
case data
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let kind = try container.decode(DataType.self, forKey: .kind)
switch kind {
case .listing:
self = .listing(try container.decode(Listing.self, forKey: .data))
case .t1:
self = .t1(try container.decode(Comment.self, forKey: .data))
case .t3:
self = .t3(try container.decode(Comment.self, forKey: .data))
case .more:
self = .more(try container.decode(More.self, forKey: .data))
}
}
}
I'm using a model so model.listings
should contain the result data parsed in the code below
let decoder = JSONDecoder()
var result = try decoder.decode([Parse].self, from: data!)
self.listings = result
In the terminal, if I PO model.listings
the data is present
Here is an example
▿ 2 elements
▿ 0 : Parse
▿ listing : Listing
▿ paginator : Paginator
▿ after : Optional<String>
- some : ""
▿ before : Optional<String>
- some : ""
▿ modhash : Optional<String>
- some : ""
▿ children : 1 element
▿ 0 : Parse
▿ t3 : Comment
▿ id : 51C7640E-D382-467B-9A65-6CAB04FA470E
- uuid : "51C7640E-D382-467B-9A65-6CAB04FA470E"
▿ title : Optional<String>
- some : "test"
▿ score : Optional<Int>
- some : 88
- replies : nil
My issue is that I don't know how to handle that data
I've tried with something like:
var test = model.listings.map( { $0.listing } )
But it says "Enum case 'listing' cannot be used as an instance member"
Also tried this way:
var test = model.listings.listing[0].children
In this case the error is: Value of type '[Parse]' has no member 'listing'
I just started with swift so I'm really confused right now, what's the best way to handle that kind of data?
CodePudding user response:
Try using one of these mechanisms:
// Using a Switch to enumerate the possibilities and using a pattern to extract the associated data
switch result {
case .listing(let aListing) :
print(aListing.geo_filter)
case .t1(let comment) :
print(comment.title)
case .t3(let comment) :
print(comment.title)
}
// Using a if case with a pattern to extract one particular enum case
if case .listing(let aListing) = result {
debugPrint(aListing)
}