I am toying around/learning Swift and JSON atm and have problems correctly casting around my responses.
So, what I am trying to achieve is displaying a list of "posts" via Alamofire request. I have no problems displaying "first-level" json items like the post-ID or the "message", but when it comes to the author array I am kinda lost.
the json response comes in as an Array with no name, hence the first [
[
-{
__v: 1,
_id: "54428691a728c80424166ffb",
createDate: "2014-10-18T17:26:15.317Z",
message: "shshshshshshshhshshs",
-author: [
-{
_id: "54428691a728c80424166ffa",
userId: "543270679de5893d1acea11e",
userName: "foo"
}
]
}
Here is my corresponding VC:
Alamofire.request(.GET, "\(CurrentConfiguration.serverURL)/api/posts/\(CurrentConfiguration.currentUser.id)/newsfeed/\(CurrentConfiguration.currentMode)",encoding:.JSON)
.validate()
.responseJSON {(request, response, jsonData, error) in
let JSON = jsonData as? NSArray
self.loadPosts(JSON!)
}
tableView.delegate = self
tableView.dataSource = self
}
func loadPosts(posts:NSArray) {
for post in posts {
let id = post["_id"]! as NSString!
let message = post["message"]! as NSString!
var authorArray = post["author"]! as? [Author]!
println(authorArray)
var author:Author = Author()
author.userName = "TEST ME"
var postObj:Post = Post()
postObj.id = id
postObj.message = message
postObj.author = author
uppDatesCollection.append(postObj)
}
println(self.uppDatesCollection.count)
dispatch_async(dispatch_get_main_queue()) {
self.tableView.reloadData()
}
}
my Models for Post
class Post {
var id:String!
var message:String!
var createDate: NSDate!
var author:Array<Author>!
init () {
}
}
and Author
class Author {
var id:String?
var userId:String?
var userName:String?
init () {
}
What is the best Approach here? Should you recast the returning Array as a Dictionary and then Access it via .valueforkey? Do you somehow iterate over the array to get this stuff out?
Obviously you can not say
author.name = authorArray[3] as String
Let's say you had Post class like so:
class Post : Printable {
var identifier:String!
var message:String!
var createDate: NSDate!
var authors:[Author]!
var description: String { return "<Post; identifier = \(identifier); message = \(message); createDate = \(createDate); authors = \(authors)" }
}
Your JSON has only one author in it, but given that it appears to be an array in the JSON, I assume it should be an array in the object model, too, as shown above. The Author class might be defined as so:
class Author : Printable {
var identifier:String!
var userId:String!
var userName:String!
var description: String { return "<Author; identifier = \(identifier); userId = \(userId); userName = \(userName)>" }
}
I wasn't sure why you made some of your optionals implicitly unwrapped (defined with !) and others not (defined with ?), so I just made them all implicitly unwrapped. Adjust as appropriate to your business rules.
Also, let's say your JSON looked like so (I wasn't quite sure what to make of the - in the JSON in your question, so I cleaned it up and added a second author):
[
{
"__v": 1,
"_id": "54428691a728c80424166ffb",
"createDate": "2014-10-18T17:26:15.317Z",
"message": "shshshshshshshhshshs",
"author": [
{
"_id": "54428691a728c80424166ffa",
"userId": "543270679de5893d1acea11e",
"userName": "foo"
},
{
"_id": "8434059834590834590834fa",
"userId": "345903459034594355cea11e",
"userName": "bar"
}
]
}
]
Then the routine to parse it might look like:
func loadPosts(postsJSON: NSArray) {
var posts = [Post]()
for postDictionary in postsJSON {
let post = Post()
let createDateString = postDictionary["createDate"] as String
post.message = postDictionary["message"] as String
post.identifier = postDictionary["_id"] as String
post.createDate = createDateString.rfc3339Date()
if let authorsArray = postDictionary["author"] as NSArray? {
var authors = [Author]()
for authorDictionary in authorsArray {
let author = Author()
author.userId = authorDictionary["userId"] as String
author.userName = authorDictionary["userName"] as String
author.identifier = authorDictionary["_id"] as String
authors.append(author)
}
post.authors = authors
}
posts.append(post)
}
// obviously, do something with `posts` array here, either setting some class var, return it, whatever
}
And this is my conversion routine from String to NSDate:
extension String {
/// Get NSDate from RFC 3339/ISO 8601 string representation of the date.
///
/// For more information, see:
///
/// https://developer.apple.com/library/ios/qa/qa1480/_index.html
///
/// :returns: Return date from RFC 3339 string representation
func rfc3339Date() -> NSDate? {
let formatter = NSDateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
formatter.timeZone = NSTimeZone(forSecondsFromGMT: 0)
formatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
return formatter.dateFromString(self)
}
}
Related
I have 3 arrays when I insert data inside table than that data also add in the array (key, value pair).
var person = ["ABC","XYZ","PQR"]
var email = ["abc#yahoo.com","xyz#yahoo.com","pqr#yahoo.com"]
var mobile = ["1234567890","1234567890","1234567890"]
My problem is how to create JSON object and data store key value pair.
I want this
{
"blogs": [
{
"person": "ABC",
"email": "abc#yahoo.com",
"contact": "1234567890"
},
{
"person": "XYZ",
"email": "xyz#yahoo.com",
"contact": "1234567890"
},
{
"person": "PQR",
"email": "pqr#yahoo.com",
"contact": "1234567890"
}
]
}
so that data passes to url()
In the action button that adds data in array and table
#IBAction func meeting_info(_ sender: Any) {
var PersonName = person_name.text
var Email = email_id.text
var MobileNo = mobile_no.text
if (person_name.text?.isEmpty)! || (email_id.text?.isEmpty)! || (mobile_no.text?.isEmpty)! {
displayMyAlertMessage(userMessage: "please check field empty or not");
}
else{
person.append(person_name.text!)
email.append(email_id.text!)
mobile.append(mobile_no.text!)
meetingTableView.reloadData()
}
}
I want to generate JSON array from person, email and contact in key value pairs
to answer your question.
var person = ["ABC","XYZ","PQR"]
var email = ["abc#yahoo.com","xyz#yahoo.com","pqr#yahoo.com"]
var mobile = ["1234567890","1234567890","1234567890"]
var paramCollection = [Any]()
var index = 0
for personData in person {
var dataCollection = [String:Any]()
dataCollection["person"] = personData
dataCollection["email"] = email[index]
dataCollection["contact"] = mobile[index]
paramCollection.append(dataCollection)
index += 1
}
let finalParameter = ["blogs":paramCollection]
}
//This will do the trick but to make it more robust you should rethink your design
// maybe use struct to store a persons data
struct Blog {
var person: String
var email: String
var mobile: String
init(name:String, email:String, phone:String) {
self.person = name
self.email = email
self.mobile = phone
}
}
//and instead of having three arrays holding three different property, you can have one array of
var blogArray = [Blog]()
//You understand where I'm going with this
This is not a great design by choice to have multiple arrays relating to the data of same Entity.
Ideally create an Entity Model called Blog with fields like personName, email, mobileNo like below -
struct Blog {
var personName: String?
var email: String?
var mobileNo: String?
}
And then in your code have an array of this to save the data then you can directly convert it into Json using the link
Convert Custom Structs to Json
Try this:
let jsonObject: [String: Any]?
let array: [[String: Any]] = [[:]]
for i in 0..person.count {
let dict = ["person": person[i],
"email": email[i],
"contact": mobile[i]]
array.append(dict)
}
jsonObject = ["blogs": array]
let validateJson = JSONSerialization.isValidJSONObject(jsonObject)
if validateJson {
//Go Ahead
}
let dictionary = ["key1": "value1", "key2": "value2"]
let jsonData = try? JSONSerialization.data(withJSONObject: dictionary, options: .prettyPrinted)
// Verifying it worked:
let parsedObject = try! JSONSerialization.jsonObject(with: jsonData!, options: .allowFragments)
I have classes like these:
class MyDate
{
var year : String = ""
var month : String = ""
var day : String = ""
init(year : String , month : String , day : String) {
self.year = year
self.month = month
self.day = day
}
}
class Lad
{
var firstName : String = ""
var lastName : String = ""
var dateOfBirth : MyDate?
init(firstname : String , lastname : String , dateofbirth : MyDate) {
self.firstName = firstname
self.lastName = lastname
self.dateOfBirth = dateofbirth
}
}
class MainCon {
func sendData() {
let myDate = MyDate(year: "1901", month: "4", day: "30")
let obj = Lad(firstname: "Markoff", lastname: "Chaney", dateofbirth: myDate)
let api = ApiService()
api.postDataToTheServer(led: obj)
}
}
class ApiService {
func postDataToTheServer(led : Lad) {
// here i need to json
}
}
And I would like to turn a Lad object into a JSON string like this:
{
"firstName":"Markoff",
"lastName":"Chaney",
"dateOfBirth":
{
"year":"1901",
"month":"4",
"day":"30"
}
}
EDIT - 10/31/2017: This answer mostly applies to Swift 3 and possibly earlier versions. As of late 2017, we now have Swift 4 and you should be using the Encodable and Decodable protocols to convert data between representations including JSON and file encodings. (You can add the Codable protocol to use both encoding and decoding)
The usual solution for working with JSON in Swift is to use dictionaries. So you could do:
extension Date {
var dataDictionary {
return [
"year": self.year,
"month": self.month,
"day": self.day
];
}
}
extension Lad {
var dataDictionary {
return [
"firstName": self.firstName,
"lastName": self.lastName,
"dateOfBirth": self.dateOfBirth.dataDictionary
];
}
}
and then serialize the dictionary-formatted data using JSONSerialization.
//someLad is a Lad object
do {
// encoding dictionary data to JSON
let jsonData = try JSONSerialization.data(withJSONObject: someLad.dataDictionary,
options: .prettyPrinted)
// decoding JSON to Swift object
let decoded = try JSONSerialization.jsonObject(with: jsonData, options: [])
// after decoding, "decoded" is of type `Any?`, so it can't be used
// we must check for nil and cast it to the right type
if let dataFromJSON = decoded as? [String: Any] {
// use dataFromJSON
}
} catch {
// handle conversion errors
}
If you just need to do this for few classes, providing methods to turn them into dictionaries is the most readable option and won't make your app noticeably larger.
However, if you need to turn a lot of different classes into JSON it would be tedious to write out how to turn each class into a dictionary. So it would be useful to use some sort of reflection API in order to be able to list out the properties of an object. The most stable option seems to be EVReflection. Using EVReflection, for each class we want to turn into json we can do:
extension SomeClass: EVReflectable { }
let someObject: SomeClass = SomeClass();
let someObjectDictionary = someObject.toDictionary();
and then, just like before, we can serialize the dictionary we just obtained to JSON using JSONSerialization. We'll just need to use object.toDictionary() instead of object.dataDictionary.
If you don't want to use EVReflection, you can implement reflection (the ability to see which fields an object has and iterate over them) yourself by using the Mirror class. There's an explanation of how to use Mirror for this purpose here.
So, having defined either a .dataDictionary computed variable or using EVReflection's .toDictionary() method, we can do
class ApiService {
func postDataToTheServer(lad: Lad) {
//if using a custom method
let dict = lad.dataDictionary
//if using EVReflection
let dict = lad.toDictionary()
//now, we turn it into JSON
do {
let jsonData = try JSONSerialization.data(withJSONObject: dict,
options: .prettyPrinted)
// send jsonData to server
} catch {
// handle errors
}
}
}
May this GitHub code will help you.
protocol SwiftJsonMappable {
func getDictionary() -> [String: Any]
func JSONString() -> String
}
extension SwiftJsonMappable {
//Convert the Swift dictionary to JSON String
func JSONString() -> String {
do {
let jsonData = try JSONSerialization.data(withJSONObject: self.getDictionary(), options: .prettyPrinted)
// here "jsonData" is the dictionary encoded in JSON data
let jsonString = String(data: jsonData, encoding: .utf8) ?? ""
// here "decoded" is of type `Any`, decoded from JSON data
return jsonString
// you can now cast it with the right type
} catch {
print(error.localizedDescription)
}
return ""
}
//Convert Swift object to Swift Dictionary
func getDictionary() -> [String: Any] {
var request : [String : Any] = [:]
let mirror = Mirror(reflecting: self)
for child in mirror.children {
if let lable = child.label {
//For Nil value found for any swift propery, that property should be skipped. if you wanna print nil on json, disable the below condition
if !checkAnyContainsNil(object: child.value) {
//Check whether is custom swift class
if isCustomType(object: child.value) {
//Checking whether its an array of custom objects
if isArrayType(object: child.value) {
if let objects = child.value as? [AMSwiftBase] {
var decodeObjects : [[String:Any]] = []
for object in objects {
//If its a custom object, nested conversion of swift object to Swift Dictionary
decodeObjects.append(object.getDictionary())
}
request[lable] = decodeObjects
}
}else {
//Not an arry, and custom swift object, convert it to swift Dictionary
request[lable] = (child.value as! AMSwiftBase).getDictionary()
}
}else {
request[lable] = child.value
}
}
}
}
return request
}
//Checking the swift object is swift base type or custom Swift object
private func isCustomType(object : Any) -> Bool {
let typeString = String(describing: type(of: object))
if typeString.contains("String") || typeString.contains("Double") || typeString.contains("Bool") {
return false
}
return true
}
//checking array
private func isArrayType(object : Any) -> Bool {
let typeString = String(describing: type(of: object))
if typeString.contains("Array"){
return true
}
return false
}
//Checking nil object
private func checkAnyContainsNil(object : Any) -> Bool {
let value = "\(object)"
if value == "nil" {
return true
}
return false
}
}
https://github.com/anumothuR/SwifttoJson
I'm trying to work with JSON as MVC model, for this I did:
// Country.swift
import SwiftyJSON
class Country {
var code: String!
var dialCode: Int!
var name: String!
init(json: JSON) {
for i in 0...json["countries"].count - 1 {
if let code = json["countries"][i]["code2"].string, dialCode = json["countries"][i]["dialCode"].string, name = json["countries"][i]["name"].string {
self.code = code
self.dialCode = Int(dialCode)
self.name = name
}
}
}
}
and later in my ViewController I do:
var countries = [Country]()
Alamofire.request(.POST, "\(property.host)\(property.getCountryList)", parameters: parameters, encoding: .JSON).responseJSON { response in
do {
let json = JSON(data: response.data!)
countries.append(Country(json: json))
} catch _ {
}
}
but I have a problem. When I print values in Country.swift file, I get results, but when I print(countries) it returns me [Project.Country] and count returns 1. What is the problem? What I do wrong?
Unless I've misunderstood is this not your desired behaviour?
countries is an array of Project.Country, which swift is representing by printing [Project.Country] (an array containing one instance of your class). There is no issue. If you want to prove that the array contains a Project.Country you should print one of the class' properties: print(countries.first.name)
EDIT: problem is you are passing a JSON array of countries to a single init method, which is just setting the properties of itself for every country and not creating an instance for each. Hence you only have one instance returned
Your problem is you are passing countries array to init method which is called only once you must do it like here
class Country {
var code: String!
var dialCode: Int!
var name: String!
init(json: JSON) {
if let code = json["code2"].string, dialCode = json["dialCode"].string, name = json["name"].string {
self.code = code
self.dialCode = Int(dialCode)
self.name = name
}
}
}
And loop here
Alamofire.request(.POST, "", parameters: nil, encoding: .JSON).responseJSON { response in
if let jsonResponse = response.result.value{
let json = JSON(jsonResponse)
for countriesJSON in json["countries"].arrayValue{
self.countries.append(Country(json: countriesJSON))
}
print(self.countries.count)
}
}
I'm using Alamofire and am parsing the returned JSON into an object as shown below:
final class User: NSObject, ResponseObjectSerializable {
var id: Int
var facebookUID: String?
var email: String
var firstName: String
var lastName: String
var phone: String?
var position: String?
var timeCreated: CVDate
init?(response: NSHTTPURLResponse, var representation: AnyObject) {
if let dataRepresentation = ((representation as! NSDictionary).valueForKey("data") as? [String: AnyObject]) {
representation = dataRepresentation
}
if let id = representation.valueForKeyPath("id") as? Int {
self.id = id
} else {
self.id = 0
}
if let facebookUID = representation.valueForKeyPath("facebook_UID") as? String {
self.facebookUID = facebookUID
}
if let email = representation.valueForKeyPath("email") as? String {
self.email = email
} else {
self.email = ""
}
if let firstName = representation.valueForKeyPath("first_name") as? String {
self.firstName = firstName
} else {
self.firstName = ""
}
if let lastName = representation.valueForKeyPath("last_name") as? String {
self.lastName = lastName
} else {
self.lastName = ""
}
if let phone = representation.valueForKeyPath("phone") as? String {
self.phone = phone
}
if let position = representation.valueForKeyPath("position_name") as? String {
self.position = position
}
if let timeCreated = representation.valueForKeyPath("time_created") as? String {
let formatter = NSDateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
if let date = formatter.dateFromString(timeCreated) {
self.timeCreated = CVDate(date: date)
} else {
self.timeCreated = CVDate(date: NSDate())
}
} else {
self.timeCreated = CVDate(date: NSDate())
}
}
}
My question is, is this style the best way to decode JSON and set the non-optional instance variables? For example, in this statement:
if let id = representation.valueForKeyPath("id") as? Int {
self.id = id
}
I am required by the compiler to add an else clause and set the id to something otherwise xCode throws an error saying: self.id is not initialized at implicitly generated super.init call.
But at the same time, intializing self.id with a value of 0 is wrong and doesn't help me at all.
But at the same time, intializing self.id with a value of 0 is wrong and doesn't help me at all.
If having a default value for self.id feels wrong, then you should make this property an Optional. That way you wouldn't have to add an else clause:
final class User: NSObject, ResponseObjectSerializable {
var id: Int?
var facebookUID: String?
var email: String
var firstName: String
var lastName: String
var phone: String?
var position: String?
var timeCreated: CVDate
init?(response: NSHTTPURLResponse, var representation: AnyObject) {
if let dataRepresentation = ((representation as! NSDictionary).valueForKey("data") as? [String: AnyObject]) {
representation = dataRepresentation
}
if let id = representation.valueForKeyPath("id") as? Int {
self.id = id
}
...
Update
You said in the comments:
I always need to have an id for the user object though.
If you have to have this id property then the question is moot, you just have to do
let id = representation.valueForKeyPath("id") as! Int
and guarantee earlier that this value will exist.
Because if your object needs an ID, then you can't initialize it anyway if this value doesn't exist and if you don't want a default value.
You could use ?? to provide default values like this:
self.id = (representation.valueForKeyPath("id") as? Int) ?? 0
While the ResponseObjectSerializable code is a great example from the Alamofire project, it's really a better idea to use a dedicated JSON parsing library that has actual error states. This is far better than using optionals to represent error states, or having to provide a default value for every field just in case the response isn't correctly formed.
Although it has a bit of learning curve, I prefer to use Argo for my JSON parsing. Once you get the hang of it it makes JSON parsing practically bulletproof. Better yet, it's easy to integrate with Alamofire, especially version 3 that was released today.
To address your concern about not having an ID being an error condition, you could use a failable initializer. I did that in a recent project. Looks something like this:
let id: Int!
init? (inputJson: NSDictionary) {
if let id = inputJson["id"] as? Int {
self.id = id
} else {
// if we are initing from JSON, there MUST be an id
id = nil
cry(inputJson) // this logs the error
return nil
}
}
Of course, this means your code will need to accept that the initialization of your entire object may fail ..
I am very new to programming, let alone Swift. I understand some concepts from previous attempts at programming so I have gotten further than ever before. I apologize if I am not clear in what I need.
I am pulling in JSON data of a list of alerts and I am trying to parse the data with swiftyJSON which I think is working out ok but I have run into a snag of trying to grab some data from some dictionaries within an array, and unfortunately inside a dictionary inside this arrary is where the email address is, and the different dictionaries use similar keys within each other.
I am going to show you my struct, fucntion and JSON data. Please help me grab the email address, service - its ID and its label. Also, there may be more than one Service as in the data shown and I need to capture all of them.
HERE IS THE JSON DATA:
{
"hasNext": false,
"data": [
{
"status": [
1,
"READ"
],
"resolutionStatus": [
0,
"OPEN"
],
"description": "There is some description here",
"title": "Some Activity",
"entities": [
{
"view_name": "audits",
"type": "link",
"parameters": {
"orgUnit": "/"
},
"label": "/"
},
{
"type": "user",
"id": "hidden#hidden.com",
"label": "hidden#hidden.com"
},
{
"type": "service",
"id": 6666,
"label": "someService"
},
{
"type": "service",
"id": 7777,
"label": "anotherService"
}
],
"stories": [
5
],
"date": "2014-12-10T23:46:28.067000Z",
"audits": [
"ljBhqKQVOF9w",
"pISQyT9iy9w",
"oynGf2_CIw"
],
"_id": "54fdad0dfd",
"id": [
14683,
"ALERT_SOME_ACTIVITY"
],
"severity": [
5,
"HIGH"
]
}
Here is my Struct:
struct AlertModel: Printable {
let alertUser: String?
let alertService: String?
let alertTitle: String?
let alertReadStatus: String?
let alertResolutionStatus: String?
let alertDescription: String?
let alertEntities: Array <String> = []
let alertDate: String?
let alertAudits: Array <String> = []
let alertId: String?
let
alertSeverity: String?
// change description to print to console
var description: String {
return "User: \(alertUser)\nService: \(alertService)\nTitle: \(alertTitle!)\nRead Status: \(alertReadStatus!)\nResolution Status: \(alertResolutionStatus!)\nDescription: \(alertDescription!)\nDate: \(alertDate!)\nAlert ID: \(alertId!)\nSeverity: \(alertSeverity!)\n******************************************\n"
}
init(alertUser: String?, alertService: String?, alertTitle: String?, alertReadStat
us: String?, alertResolutionStatus: String?, alertDescription: String?/*, alertEntities: Array<String>*/, alertDate: String?/*, alertAudits: Array<String>*/, alertId: String?, alertSeverity: String?) {
self.alertUser = alertUser
self.alertService = alertService
self.alertTitle = alertTitle
self.alertReadStatus = alertReadStatus
self.alertResolutionStatus = alertResolutionStatus
self.alertDescription = alertDescription
//self.alertEntities = alertEntities
self.alertDate = alertDate
//self.alertAudits = alertAudits
self.alertId = alertId
self.alertSeverity = alertSeverity
}
AND HERE IS THE FUNCTION:
let jsonAlert = JSON(data: jsonAlertObject)
if let alertArray = jsonAlert["data"].array {
var alerts = [AlertModel]()
for alertDict in alertArray {
let alertTitle: String? = alertDict["title"].stringValue
let alertReadStatus: String? = alertDict["status"][1].stringValue
let alertResolutionStatus: String? = alertDict["resolutionStatus"][1].stringValue
let alertDescription: String? = alertDict["description"].stringValue
let alertDate: String? = alertDict["date"].stringValue
let alertId: String? = alertDict["_id"].stringValue
// Need to grab the type and label from each dictionary in the array of entities
let alertEntitiesArray: Array? = alertDict["entities"].arrayObject
var arrayIndex = 0
var entitiesDict = ["" : ""]
while arrayIndex < alertEntitiesArray?.count {
entitiesDict[alertDict["entities"][arrayIndex]["type"].stringValue] = alertDict["entities"][arrayIndex]["label"].stringValue
arrayIndex++
}
let alertService: String? = entitiesDict["service"]
let alertUser: String? = entitiesDict["user"]
let alertSeverity: String? = alertDict["severity"][1].stringValue
let alert = AlertModel(alertUser: alertUser, alertService: alertService, alertTitle: alertTitle, alertReadStatus: alertReadStatus, alertResolutionStatus: alertResolutionStatus, alertDescription: alertDescription, alertDate: alertDate, alertId: alertId, alertSeverity: alertSeverity)
alerts.append(alert)
var alertsDictionaryByID = [alertId!: alert]
}
println(alerts)
}
As you can see the JSON data is a few levels deep. I have no problem getting to the data and pulling it out. The problem is the "Entities" array may not always have the same data in it. It my have multiple services, it may have no email address, it may have a completely different set of data for the first value of the array.
I am trying to get the email address out. If I could find a way to search for the "user" as with the dictionary data and then when found it would return the array index value to be able to reference it directly because I will never know with index number the user value is part of.
I hope I came across clear enough and someone can help me. --- my next step will be populating a listView with each individual alert.
I was also using SwiftyJSON, but using NSURLConnection was easy. Like this method.
//MARK: - NSURLConnection Delegate methods
var responseData : NSMutableData = NSMutableData()
func connection(connection: NSURLConnection!, didReceiveResponse response: NSURLResponse!)
{
self.responseData.length = 0
}
func connection(connection: NSURLConnection!, didReceiveData data: NSData!)
{
self.responseData.appendData(data)
}
func connectionDidFinishLoading(connection: NSURLConnection!)
{
if let responseDatas = responseData as NSData? {
if let jsonResult : NSDictionary = NSJSONSerialization.JSONObjectWithData(responseDatas, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary? {
if let dataArray = jsonResult.valueForKeyPath("data") as? NSArray
{
if let entitiesArray = dataArray.valueForKeyPath("entities") as? NSArray
{
if let firstArray = dataArray[0]
{
// access your viewName and types here
}
// Like this method, convert all your parameters and access it.
}
}
else
{
// Do something here
}
}
else
{
// Do something here
}
}
else
{
// Do something here
}
}
func connection(connection: NSURLConnection!, didFailWithError error: NSError!)
{
// Do something here
}
I ended up finding SwiftyJSON and Alamofire to significantly assist with the networking and JSON Serialization.
As far as my issue with the dictionaries within the array I ended up creating a function that iterated through the entities array looking at each dictionary seperately and then performed a Switch statement based on the key="type" to determine if it was the "user" dictionary or the "service" dictionary and then combined the 'type' value, which said if it was a user or a service, with the value of "label", which is the the username or service name, and created a new dictionary out of that which I could then reference to put back into my data model.
class func retrieveDataFromEntitiesArray (alertDict: JSON) -> (entitesDict: Dictionary<String, String>, servicesArray: [String]) {
// Need to create an array object, instead of a JSON object, of the entities array to be able to get a count to run the while against.
var arrayIndex = 0
var entitiesDict: Dictionary<String, String> = [:]
var alertEntitiesArray = alertDict.arrayObject
var servicesArray = [String]()
while arrayIndex < alertEntitiesArray?.count {
var dictKey = alertDict[arrayIndex]["type"].string
switch (dictKey!) {
case "user":
entitiesDict[alertDict[arrayIndex]["type"].stringValue] = alertDict[arrayIndex]["label"].stringValue
case "service":
servicesArray.append(alertDict[arrayIndex]["label"].stringValue)
case "policyRule":
entitiesDict[alertDict[arrayIndex]["type"].stringValue] = alertDict[arrayIndex]["label"].stringValue
default:
println("Nothing Here")
}
arrayIndex++
}
return (entitiesDict, servicesArray)
}