iosjsonswiftnsdictionary

Unable to parse a JSON data in swift


I have a API response as given below:

{
    "status": 200,
    "schedule_data": {
        "2020_08_16_1597485600": {
            "schedule_date": "2020-08-16",
            "nanny_id": 2,
            "shift_start": "06:00",
            "shift_end": "13:00",
            "schedule_id": 112
        },
        "2020_08_16": {
            "schedule_date": "2020-08-16",
            "nanny_id": 2,
            "shift_start": "",
            "shift_end": "",
            "schedule_id": 0
        },
        "2020_08_17_1597485600": {
            "schedule_date": "2020-08-17",
            "nanny_id": 2,
            "shift_start": "06:00",
            "shift_end": "22:00",
            "schedule_id": 113
        },
        "2020_08_17": {
            "schedule_date": "2020-08-17",
            "nanny_id": 2,
            "shift_start": "",
            "shift_end": "",
            "schedule_id": 0
        },
        "2020_08_18": {
            "schedule_date": "2020-08-18",
            "nanny_id": 2,
            "shift_start": "",
            "shift_end": "",
            "schedule_id": 0
        },
        "2020_08_19": {
            "schedule_date": "2020-08-19",
            "nanny_id": 2,
            "shift_start": "",
            "shift_end": "",
            "schedule_id": 0
        },
        "2020_08_20": {
            "schedule_date": "2020-08-20",
            "nanny_id": 2,
            "shift_start": "",
            "shift_end": "",
            "schedule_id": 0
        },
        "2020_08_21": {
            "schedule_date": "2020-08-21",
            "nanny_id": 2,
            "shift_start": "",
            "shift_end": "",
            "schedule_id": 0
        },
        "2020_08_22": {
            "schedule_date": "2020-08-22",
            "nanny_id": 2,
            "shift_start": "",
            "shift_end": "",
            "schedule_id": 0
        },
        "2020_08_23": {
            "schedule_date": "2020-08-23",
            "nanny_id": 2,
            "shift_start": "",
            "shift_end": "",
            "schedule_id": 0
        },
        "2020_08_24": {
            "schedule_date": "2020-08-24",
            "nanny_id": 2,
            "shift_start": "",
            "shift_end": "",
            "schedule_id": 0
        },
        "2020_08_25": {
            "schedule_date": "2020-08-25",
            "nanny_id": 2,
            "shift_start": "",
            "shift_end": "",
            "schedule_id": 0
        },
        "2020_08_26": {
            "schedule_date": "2020-08-26",
            "nanny_id": 2,
            "shift_start": "",
            "shift_end": "",
            "schedule_id": 0
        },
        "2020_08_27": {
            "schedule_date": "2020-08-27",
            "nanny_id": 2,
            "shift_start": "",
            "shift_end": "",
            "schedule_id": 0
        },
        "2020_08_28": {
            "schedule_date": "2020-08-28",
            "nanny_id": 2,
            "shift_start": "",
            "shift_end": "",
            "schedule_id": 0
        },
        "2020_08_29": {
            "schedule_date": "2020-08-29",
            "nanny_id": 2,
            "shift_start": "",
            "shift_end": "",
            "schedule_id": 0
        },
        "2020_08_30": {
            "schedule_date": "2020-08-30",
            "nanny_id": 2,
            "shift_start": "",
            "shift_end": "",
            "schedule_id": 0
        },
        "2020_08_31": {
            "schedule_date": "2020-08-31",
            "nanny_id": 2,
            "shift_start": "",
            "shift_end": "",
            "schedule_id": 0
        }
    }
}

I have the data model for this API response and it is as follows:

import Foundation

struct Welcome: Codable {
    let status: Int
    let scheduleData: [String: ScheduleDatum]

    enum CodingKeys: String, CodingKey {
        case status
        case scheduleData = "schedule_data"
    }
}

// MARK: - ScheduleDatum
struct ScheduleDatum: Codable {
    let scheduleDate: String?
    let nannyID: Int?
    let shiftStart: String?
    let shiftEnd: String?
    let scheduleID: Int?

    enum CodingKeys: String, CodingKey {
        case scheduleDate = "schedule_date"
        case nannyID = "nanny_id"
        case shiftStart = "shift_start"
        case shiftEnd = "shift_end"
        case scheduleID = "schedule_id"
    }
}

I want the schedule_date values for the data where the schedule_id is not zero. This schedule_data is an array of dictionary. The JSON parsing is done this way in the iOS swift code:

let decoder = JSONDecoder()
      
      do {
          
          let user = try decoder.decode(ScheduleListModel.self, from: response.data!)
          self.listdata = user
       

       
        if (self.listdata?.scheduleData.count)! > 0
       {

       }
       else
       {
        self.showAlert(message: "No schedule available")
       }
       
         } catch {
             debugPrint(error)
      }

How to fetch the values inside the dictionary of this array?


Solution

  • There are a few things to be improved here. First, the model properties don't have to be optional if the keys never become nil. Secondly, the coding keys are not required as the same can be achieved by convertFromSnakeCase.

    Model:

    let data = Data(string.utf8)
    
    struct Welcome: Codable {
        let status: Int
        let scheduleData: [String: ScheduleDatum]
    }
    
    struct ScheduleDatum: Codable {
        let scheduleDate: String
        let nannyId: Int
        let shiftStart: String
        let shiftEnd: String
        let scheduleId: Int
    }
    

    Decoding needs to be done to the model Welcome. Also, loop through the data to get the scheduleDates. Here's how:

    do {
        let decoder = JSONDecoder()
        decoder.keyDecodingStrategy = .convertFromSnakeCase
    
        let user = try decoder.decode(Welcome.self, from: response.data)
        var scheduleDates = [String]()
    
        for schedule in user.scheduleData {
            if schedule.value.scheduleId != 0 {
                scheduleDates.append(schedule.value.scheduleDate)
            }
        }
        print(scheduleDates)
    } catch {
        debugPrint(error)
    }