I have to decode a given JSON structure coming from an API in Swift 4. The problem is that at some point in the tree I have at the same level different kind of datas and one of the type can have sub elements.
I've tried several JSONDecoder and Decodable techniques but so far I havn't find a solution.
Simplified JSON :
{
"menuName": "Menu 1",
"menuId": 1,
"menuGroups": [
{
"type": "group",
"name": "Group 1",
"menuEntry": [
{
"type": "group",
"name": "Sub Group 1.1",
"menuEntry": [
{
"type": "menuItem",
"productName": "Item 1",
"productPrice": "9.00"
},
{
"type": "menuItem",
"productName": "Item 2",
"productPrice": "12.00"
}
]
}, {
"type": "menuItem",
"productName": "Item 3",
"productPrice": "9.00"
}
]
}
]
}
Here are the decodables I'm trying to use :
struct Menu: Decodable {
let menuName: String
let menuId: Int
let categories: [MenuCategory]
enum CodingKeys : String, CodingKey {
case menuName
case menuId
case categories = "menuGroups"
}
}
struct MenuCategory: Decodable {
let type: String
let name: String
let items: [CategoryItem]
enum CodingKeys : String, CodingKey {
case type
case name
case items = "menuEntry"
}
}
enum CategoryItem: Decodable {
case group(MenuCategory)
case menuItem(MenuItem)
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
do {
let item = try container.decode(MenuCategory.self)
self = .group(item)
return
} catch let err {
print("error decoding category: \(err)")
}
do {
let item = try container.decode(MenuItem.self)
self = .menuItem(item)
return
} catch let err {
print("error decoding item: \(err)")
}
try self.init(from: decoder)
}
}
struct MenuItem: Decodable {
let type: String
let productName: String
let productPrice: String
enum CodingKeys : String, CodingKey {
case type = "type"
case productName
case productPrice
}
}
I think that using :
let container = try decoder.singleValueContainer()
is wrong because the container shouldn't be a single value container, but I don't know what to choose / do from here...
Would anyone have an idea on that ? How would you decode some JSON like in the example ?