2

I would like to handle a JSON string that is returned as data from a HTTP call made using Alamofire.

This question uses SwiftyJSON.

However I wanted to go a little bit "lower level" and understand how to convert the response object into a dictionary.

Reasoning is that it feels that a dictionary may be a simple / easy way to access to the JSON values in the response (rather than having to go through the process of converting the response to a JSON object).

This is under the assumption that JSON objects and dictionaries are the same thing (are they?).

Here is the sample function that I wrote:

func question() -> Void{
    let response : DataRequest = Alamofire.request("http://aapiurl", parameters: nil)

    // Working with JSON Apple developer guide:
    // https://developer.apple.com/swift/blog/?id=37

    response.responseJSON { response in
        if let JSON  = response.result.value
        {

            print("JSON: \(JSON)") // Works!

            let data  = JSON as! NSMutableDictionary
            // Casting fails
            // Could not cast value of type '__NSCFArray' (0x19f952150) to 'NSMutableDictionary' (0x19f9523f8).
            print("Data: \(data)")
        }
    }
}

EDIT:

The JSON object seems to be of type Any and does not have any of the methods that are suggested in the answers below.

I have tried to convert it to a Dictionary and got the error below:

enter image description here

mm24
  • 9,280
  • 12
  • 75
  • 170
  • Here `data` is of `NSArray` type. You can try with `let data = JSON as! NSArray`. – Bharat Nakum Jan 12 '17 at 12:52
  • Mhh... yep makes sense. I could iterate over the array and convert it to a Dictionary (http://stackoverflow.com/questions/31446960/convert-swift-array-to-dictionary-with-indexes). Is this best practice? What do you normally do? – mm24 Jan 12 '17 at 12:55
  • just do like JSON.mutablearray("key") as! NSMutableDictionary – Mahesh Giri Jan 12 '17 at 13:02

3 Answers3

0

A JSON object IS a Dictionary (or possibly an Array at top level).

Note that you should not be using NSMutableDictionary or NSDictionary (or NSArray or NSMutableArray) in Swift.

Also, JSON objects are not working objects. JSON is a way to move data around. It is not to be used as a data source.

If you want to edit the information you get from JSON then you should construct proper data objects from that JSON and work with them.

If you then need to send JSON from this new data then you take your data objects and convert them back to dictionaries and arrays (i.e. JSON objects) and send that data.

Fogmeister
  • 76,236
  • 42
  • 207
  • 306
  • Thanks for the answer. What is the best practice for accessing JSON objects in your experience? One of the comments above suggested that the data that I get as response is of an Array type.. it feels not straightforward to convert the array in a usable JSON object (where I can list all the keys and values). – mm24 Jan 12 '17 at 13:00
  • @mm24 If the JSON is an array then it will be an array of things. To access keys and values in an array doesn't make sense. You should convert the JSON to an array of actual Swift objects (probably structs). Once you've done that just forget about the JSON. – Fogmeister Jan 12 '17 at 13:01
  • when I look into the variable JSON it says that is of type Any. When I try to cast to a dictionary it fails (see updated question). – mm24 Jan 12 '17 at 13:16
  • @mm24 what is displayed if you just print the JSON? – Fogmeister Jan 12 '17 at 14:02
  • This answer does not give detail as to how to do what it recommends. The OPs question is not answered here. – calderonmluis Sep 29 '17 at 19:58
0

Alamofire has the result value of type Any because it usually would be an array or a dictionary. In Swift you normally shouldn't use NS* classes, but rather native swift types such as Array and Dictionary.

You can (should) use optionals to look into the returned JSON object:

if let array = response.result.value as? [Any] {
    print("Got an array with \(array.count) objects")
}
else if let dictionary = response.result.value as? [AnyHashable: Any] {
    print("Got a dictionary: \(dictionary)")
}
...

Depending on what you expect from your backend, you can treat each of the cases as a success or a failure.

hybridcattt
  • 3,001
  • 20
  • 37
-1
    Alamofire.request(myUrl)
        .responseJSON  {
            response in

            if let dict = response.result.value as? [String : Any] {

               debugPrint(dict)

               wishLists.removeAll()  //[[String:Any]]

               let lists = dict["wishlists"] as! [String: Any]

               debugPrint(lists)

               for (key, value) in lists {

                   var list = value as! [String: Any]

                    wishLists.append(list)

                }

                debugPrint(wishLists)

                self.tableView.reloadData()

            }

    }
markhorrocks
  • 1,199
  • 19
  • 82
  • 151
  • This is not how Alamofire works. Using the `responseJSON` already parses the data into JSON objects. Besides, the OP os not asking how to parse data into JSON. – Fogmeister Jan 12 '17 at 13:03
  • Would you have some example code on how to handle the responseJSON data? I would like to access the key / value pairs of the JSON object. – mm24 Jan 12 '17 at 13:19
  • I edited my answer in view of the above comment by @Fogmeister – markhorrocks Jan 12 '17 at 14:24