3

I am trying to convert a swift object to JSON, I have seen these SO questions 1 & 2, but I could not apply it to my code.

I have a swift object of type [String : DailyTimes] which I would like to convert it back to JSON data in a pure Swift 3 way, without any libraries.

Below is my custom class:

class AvailabilityTimes:{

    struct Times{
        var startTime : String?
        var endTime   : String?


    }

    struct DailyTimes{
        let weekday : String
        var available : Bool
        var times = [Times]()
        mutating func update(times: [Times]){
            self.times = times
        }

    }
}

The converted JSON data (from Swift object) would look something like this:

[
     "Monday": [ "weekday" : "Monday",
                 "available" : true,
                 "times": [
                     ["startTime": "9:00 AM", "endTime": "1:30 PM" ],
                     ["startTime": "2:30 PM", "endTime": "6:00 PM" ],
                     ["startTime": "7:30 PM", "endTime": "9:00 PM" ]
                 ]
     ],
     "Tuesday": [ "weekday" : "Tuesday",
                 "available" : true,
                 "times": [
                     ["startTime": "9:00 AM", "endTime": "6:00 PM" ]
                 ]
                 ]
     ]

My unsuccessful attempt to convert [String : DailyTimes] to JSON data

Step 1: Added convertToDictionary function in both structs.

class AvailabilityTimes:{

    struct Times{
        var startTime : String?
        var endTime   : String?

        func convertToDictionary() -> Dictionary<String, Any> {
            return [
                "startTime" : self.startTime,
                "endTime"   : self.endTime
            ]
        }
    }

    struct DailyTimes{
        let weekday : String
        var available : Bool
        var times = [Times]()
        mutating func update(times: [Times]){
            self.times = times
        }

        func convertToDictionary() -> Dictionary<String, Any> {
            return [
                "weekday"   : self.weekday,
                "available" : self.available,
                "times"     : self.times
            ]
        }

    }
} 

This is where I am unsuccessfully trying to convert to JSON data.

Step 2: Function that converts to JSON data

func convertTimesObjectToJSON(timesObject: [String : DailyTimes]){

                for (key, value) in timesObject{

                    let dictionary =  value.convertToDictionary

                    print("dictionary", dictionary)
                    do{
                        let theJSONData = try JSONSerialization.data(withJSONObject: dictionary, options: .prettyPrinted)
                    } catch let error{
                        print("error: \(error)")
                    }



                }

            }
SpaceX
  • 2,814
  • 2
  • 42
  • 68

2 Answers2

5

This method:

JSONSerialization.data(withJSONObject: dictionary, options: .prettyPrinted)

requires that dictionary to be a "property list". And a this:

        [
            "weekday"   : self.weekday,
            "available" : self.available,
            "times"     : self.times
        ]

Is not a property list.

Why? Because self.times is of type [Times], which is not a property list type. You need to call self.times.map{$0.convertToDictionary()) here so as to convert times to a property list.

func convertToDictionary() -> Dictionary<String, Any> {
    return [
        "weekday"   : self.weekday,
        "available" : self.available,
        "times"     : self.times.map{$0.convertToDictionary())
    ]
}
Sweeper
  • 213,210
  • 22
  • 193
  • 313
2

Try this :

struct DailyTimes{
    let weekday : String
    var available : Bool
    var times = [Times]()
    mutating func update(times: [Times]){
        self.times = times
    }

    func convertTimesToDictionary() -> [Any] {
        var timeDict:[Any] = []
        self.times.forEach({ timeDict.append($0.convertToDictionary())})
        return timeDict
    }

    func convertToDictionary() -> Dictionary<String, Any> {
        return [
            "weekday"   : self.weekday,
            "available" : self.available,
            "times"     : self.convertTimesToDictionary()
        ]
    }
}

Function convert to json :

func convertToJSONObject(timesObject: [String : DailyTimes]) -> [String:AnyObject] {
    var dailyTimesObject:[String:AnyObject] = [:]
    for (key, value) in timesObject {
        dailyTimesObject.updateValue(value.convertToDictionary() as AnyObject, forKey: key)
    }
    return dailyTimesObject
}

func convertTimesObjectToJSON(timesObject: [String : DailyTimes]){
    do{
        let theJSONData = try JSONSerialization.data(withJSONObject: convertToJSONObject(timesObject: timesObject), options: .prettyPrinted)
        print(String(data: theJSONData, encoding: String.Encoding.utf8)!)
    } catch let error{
        print("error: \(error)")
    }
}
Vini App
  • 7,339
  • 2
  • 26
  • 43