Search code examples
iosjsonswiftdecodable

Swift 4 - How to structure a json object and using decodable in switch (not working)


I'm trying to create a structure for the following json object using swift decodable.

{
    "template": [

            {
                "id": 8,
                "question": "Favorite Color?",
                "category": "Color",
                "section": "Favorite Colors",
                "is_active": 1,
            },
            [
                {
                    "id": 14,
                    "question_id": 8,
                    "option_name": "Red",
                    "is_active": 1,
                },
                {
                    "id": 16,
                    "question_id": 8,
                    "option_name": "Orange",
                    "is_active": 1,

                }
            ],
            {
                "id": 9,
                "question": "What cars do you drive?",
                "category": "Cars",
                "section": "Favorite Cars",
                "is_active": 1,

            },
            [
                {
                    "id": 15,
                    "question_id": 9,
                    "option_name": "Toyota",
                    "is_active": 1,
                },
                {
                    "id": 18,
                    "question_id": 9,
                    "option_name": "Honda",
                    "is_active": 1,

                },
                {
                    "id": 19,
                    "question_id": 9,
                    "option_name": "BMW",
                    "is_active": 1,

                }
            ]
        ]

}

I have some like:

public struct GameTemplate:Decodable {
 question:String?
}
 public struct Game:Decodable {
  let template[GameTemplate]
}

For some reason when i tried to parse it doesn't work i get an error stating that struct is not a dictionary. I have tried casting the struct value but that didn't work either at this point just need to get a nice and clean json object after is decoded.


Solution

  • your JSON format is not consistent.

    Just take the first category of color :

    {
    "template": [
    
            {
                "id": 8,
                "question": "Favorite Color?",
                "category": "Color",
                "section": "Favorite Colors",
                "is_active": 1,
            },
            [
                {
                    "id": 14,
                    "question_id": 8,
                    "option_name": "Red",
                    "is_active": 1,
                },
                {
                    "id": 16,
                    "question_id": 8,
                    "option_name": "Orange",
                    "is_active": 1,
    
                }
            ],
        ]
    }
    

    The template is an array having dictionary on 0 index and array on 1 index. It is decodable in a different way but that's an extra effort.

    If possible make the JSON data consistent and club categories in one index of array as :

    {
    "template": [
    
            {
                "id": 8,
                "question": "Favorite Color?",
                "category": "Color",
                "section": "Favorite Colors",
                "is_active": 1,
                "subCategory": [
                           {
                              "id": 14,
                              "question_id": 8,
                              "option_name": "Red",
                              "is_active": 1,
                           },
                           {
                              "id": 16,
                              "question_id": 8,
                              "option_name": "Orange",
                              "is_active": 1,
    
                           }
                  ]
              }
        ]
    }
    

    and the same way club the different category of cars.

    It will be easy for you to decode as:

    public struct GameTemplate:Decodable {
        question: String?
        subCategory: [SubCategory]
    }
    
    public struct SubCategory:Decodable {
        option_name: String?
    }
    
    public struct Game:Decodable {
        let template: [GameTemplate]
    }
    

    Hope you get it what I am trying to explain.