Q:

Swift Decode JSON with mixed types and possible sub structures

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 ? 

A:

use this stuct 
struct YourStruct: Codable {
    let menuName: String
    let menuID: Int
    let menuGroups: [MenuGroup]

    enum CodingKeys: String, CodingKey {
        case menuName
        case menuID = "menuId"
        case menuGroups
    }
}

struct MenuGroup: Codable {
    let type, name: String
    let menuEntry: [MenuGroupMenuEntry]
}

struct MenuGroupMenuEntry: Codable {
    let type: String
    let name: String? 
    let menuEntry: [MenuEntryMenuEntry]? 
    let productName, productPrice: String? 
}

struct MenuEntryMenuEntry: Codable {
    let type, productName, productPrice: String
}

and in datatask after cheking that you dont have an error
if let data = data {
                let decoder = JSONDecoder()
                guard let decodedJson = try?  decoder.decode(YourStruct.self, from: data) else { completion(nil) ; return }

            }

hope this help

