iOS programming, fetching JSON data - ios

I have added to my project the SwiftyJSON.swift file and I am trying to get some data from the web. Now my project runs but only until the line where I am trying to get the array from json in a dictionary. I cannot understand where the problem is, but I am guessing it has to be something very stupid as I am just in the beginning with learning swift.
I am just trying to print in the console the name of all the movies from that url and after I manage to achieve this performance, I will try to get the summary of the movie as well and then put them in a TableView.
import UIKit
class FirstViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//grab the status code and check if the transfer was successful == 200
let requestURL: NSURL = NSURL(string: "https://itunes.apple.com/us/rss/topmovies/limit=50/json")!
let urlRequest: NSMutableURLRequest = NSMutableURLRequest(URL: requestURL)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(urlRequest) {
(data, response, error) -> Void in
let httpResponse = response as! NSHTTPURLResponse
let statusCode = httpResponse.statusCode
if (statusCode == 200) {
//sort through the stations key and cast the data into an array of dictionaries
do{
let json = try NSJSONSerialization.JSONObjectWithData(data!, options:.AllowFragments)
print("bbbbb")
// From here on, it doesn't print anything anymore
if let movies = json["entry"] as? [[String: AnyObject]] {
print(movies)
print("test")
for movie in movies {
if let name = movie["name"] as? String {
print("mmmm")
print("%# (Built %#)",name)
}
}
}
}catch {
print("Error with Json: \(error)")
}
}
}
task.resume()

entry is an json array, Use .array
if let movies = json["entry"].array {
for movie in movies {
// Do stuff
}
}
Also a general tip. Do not cast the values e.g.
movie["something"] as? String
Rather use the built in features:
movie["something"].string
Update
Looking closer on your code I see that you are acctually not using SwiftyJSON.swift at all.
To use Swifty you parse the json text like this and get a JSON object:
let jsonObj = JSON(data: yourData) // data is a NSData
Please have another look at the documentation:
https://github.com/SwiftyJSON/SwiftyJSON
I think you are reading the section "Why is the typical JSON handling in Swift NOT good?". That section explains the native and "bad" way of managing json in Swift, the real documentation is further down.

Related

Reading Data in API response | iOS

I'm trying to integrate a login API in my iOS project. When i hit that API in browser it gives me correct JSON response. Whereas, when i call it in my app, i'm unable to read JSON. Code is as:
let url = NSURL(string: "myURL")
let request = NSURLRequest(URL: url!)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request) { (data, response, error) -> Void in
if error != nil {
print (error)
}
do {
//jsonDict is always nil
if let jsonDict = try self.jsonFromData(data!) {
print (jsonDict)
}
}
catch {
print ("hi")
}
}
jsonFromData is as:
private func jsonFromData(jsonData: NSData) throws -> [NSDictionary]?
{
var jsonDict: [NSDictionary]? = nil
do
{
jsonDict = try NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.AllowFragments) as? [NSDictionary]
}
catch
{
throw(error)
}
return jsonDict
}
Response of API, when hit in browser is as:
Please help me, what i am doing wrong. Thanks.
UPDATE:
I just checked that if i convert data to String, it gives correct value. i.e.
let string = NSString(data: jsonData, encoding: NSASCIIStringEncoding)
print (string)
//OUTPUT: Optional({"Authenticated":true,"CustomerID":000,"CustomerName":"TEMP","Members":[{"MemberID":000,"MemberNumber":"000","MembershipID":00,"MembershipExpiration":"\/Date(1517464799000-0600)\/","ValidBuyerTypes":[0]}]})
Look at your code where you decode the JSON and the as? statement. You are trying to get an array of NSDictionary. Your JSON as printed contains a single dictionary, not an array.
This looks right to me. The only thing I can think is that (despite what the string output looks like) the top level container of your response is NOT an NSDictionary. In your jsonFromData function, instead of assuming the result of JSONObjecWithData will be an NSDictionary, I would say:
let iDunnoWhatThisIs = try NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.AllowFragments) // don't cast this to NSDictionary
and see what you get back. It should either be a dictionary or an array, however, since you have NSJSONReadingOptions.AllowFragments set for the options, it's possible that it could be something else entirely. Start with making SURE you're actually getting back what you're assuming you are and go from there.
Try using NSKeyedUnarchiver instead:
jsonDict = NSKeyedUnarchiver.unarchiveObjectWithData(jsonData)! as NSDictionary

Use JSON data offline Swift 3

I'm a beginner so please be gentle.
Ok so I successfully parse my JSON from the server and can access all of its contents but know I'm kind of stuck here:
//Functionn for fetching API data
func fetchRates(){
//Set EndPoint URL
let url = URL(string: endPoint)
URLSession.shared.dataTask(with: url!) { (data, response, error) in
if error != nil {
print(error as Any)
}
do {
let json = try? JSONSerialization.jsonObject(with: data!, options: [])
let dictonary = json as? [String: Any?]
let ratesJson = dictonary?["rates"] as? [String: Double]
print(ratesJson as Any)
} catch let jsonError {
print(jsonError)
}
}.resume()
}
Now I want to get my ratesJson Dictionary out of this function and actually use its contents to do some calculations, but after hours of trying and searching I still have no idea how.
I just want to:
Get JSON data stored presistently (for offline use)
Update the Data when the app launches and overwrite the old data
The possibilities I've come across so far are CoreData, which seems really confusing and complicated and Realm which I don't really know at all.
Help would be very much appreciated and sorry if this seems really stupid
Since you have the JSON parsing, I would create a object class to store the data using Core Data. There is a lot that goes into core data usage at first, but it is well worth the time investment to learn if you plan on continuing iOS development. Core Data Tuts
I also do not know what you plan on doing with your app, or the purpose, and Core Data might be a little overkill according to your purpose, but you could always save the updated JSON each time, overwriting a file in the device's document's dir, then read the data back in and parse it again.
You can write the JSON data to a outputstream using:
JSONSerialization.writeJSONObject(_ obj: Any, to stream: OutputStream, options opt: JSONSerialization.WritingOptions = [], error: NSErrorPointer)
//Write JSON data into a stream. The stream should be opened and configured.
//The return value is the number of bytes written to the stream, or 0 on error.
//All other behavior of this method is the same as the dataWithJSONObject:options:error: method.
UPDATE: Ok I think I see your question now. There are two ways that you can go about getting your data back to your view controller: 1. Delegate pattern 2.Closures. I personally like using delegates over closures.
With delegates you will need to create a protocol:
protocol SessionDataTaskComplete {
func dataDownloaded(parsedJson : [String : Double])
}
And inside of your URLSession class you will need a class variable to hold that protocol delegate:
var dataTaskCompleteDelegate : SessionDataTaskComplete?
Then you will need to have your view controller implement that protocol:
class MyViewController: UIViewController, SessionDataTaskComplete {
override func viewDidLoad() {
super.viewDidLoad()
//Also assign your viewController as your URLSession's SessionDataTaskComplete delegate
myURLSession.dataTaskCompleteDelegate = self
}
func dataDownloaded(parsedJson : [String : Double]) {
//Handle data as you wish here
}
}
Now in your fetchRates() you can use that delegate to pass the data back to your viewController:
func fetchRates(){
//Set EndPoint URL
let url = URL(string: endPoint)
URLSession.shared.dataTask(with: url!) { (data, response, error) in
if error != nil {
print(error as Any)
}
do {
let json = try? JSONSerialization.jsonObject(with: data!, options: [])
let dictonary = json as? [String: Any?]
let ratesJson = dictonary?["rates"] as? [String: Double]
//print(ratesJson as Any)
if (dataTaskCompleteDelegate != nil) {
dataTaskCompleteDelegate!.dataDownloaded(parsedJson: ratesJson)
}
} catch let jsonError {
print(jsonError)
}
}.resume()
}
If you are not comfortable with using the delegate pattern, that is something else I would suggest spending time learning, as it is used all over with the iOS SDK. Try to think of them as an object assigning a duty/task to another object.

JSON parsing and returning data in Swift

i have a Swift code for retrieving and parsing JSON data from the web. everything seems to work fine except one problem i am facing right now. I tried to solve it for some time, have check all sources online.
I have created global dictionary "dicOfNeighbours" that would like to return as a result of parse to other class by calling "func startConnection".
dicOfNeighbours stores parsed data till it goes out of the closing bracket of the:
"let task = session.dataTaskWithRequest(urlRequest) { ... }"
After it stores just nil. And returned result is nil as well.
I have tried to pass "dicOfNeighbours" variable by reference using inout and it is still returns nil result.
there might some solution that i missed.
I would appreciate any help and suggestions.
Thanks!
var dicOfNeighbours = Dictionary<String, [Int]>()
func startConnection() -> Dictionary<String, [Int]>{
let requestURL: NSURL = NSURL(string: "http://www....data.json")!
let urlRequest: NSMutableURLRequest = NSMutableURLRequest(URL: requestURL)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(urlRequest) {
(data, response, error) -> Void in
let httpResponse = response as! NSHTTPURLResponse
let statusCode = httpResponse.statusCode
if (statusCode == 200) {
do{
let json = try NSJSONSerialization.JSONObjectWithData(data!, options:.AllowFragments)
if let neighbours = json["neighbours"] as? [String: Array<Int>] {
var i = 0
for (index, value) in neighbours {
self.dicOfNeighbours[index] = value
}
}
}catch {
print("Error with Json: \(error)")
}
}
}
task.resume()
return self.dicOfNeighbours
}
You are using return instead of using a callback. You are doing your parsing when the network connection is done; asynchronously.
To synchronize it, you'd need to use semaphores, but that is highly discouraged on the main thread.
Instead, do the appropriate things with the result when your completion block is executed. Think of the data task as 'do stuff, come back to me when you're done'.

How To Fetch and Parse JSON Using Swift 2 + XCode 7 + iOS 9 [duplicate]

This question already has answers here:
How to parse JSON in Swift using NSURLSession
(5 answers)
Closed 7 years ago.
Was looking for useful tutorials for networking with Swift 2 and iOS 9, but it seems that topic has no content online. I have watched the WWDC session Networking with NSURLSession But I couldn't adapt the new API of iOS9 to have an asynchronous way to fetch and parse JSON data. What I have tried:
do {
if let url = NSURL(string: "site/api.php?option=fetchOps"),
let data = NSData(contentsOfURL: url),
let jsonResult = try NSJSONSerialization.JSONObjectWithData(data, options: []) as? [[String:AnyObject]] {
}
} catch let error as NSError {
print(error.description)
}
Please share your experience with networking on iOS9 and Swift2, any best practices maybe a Singleton class for networking and parsing maybe an ORM ?
Easy way to make a request for you:
How to make an HTTP request in Swift?
Or If you want to send request by your own:
HTTP POST error Handling in Swift 2
Converting a String to JSON Object:
Just as an example, here I've converted a NSString
First of all convert the NSString to NSDictionary
static func convert(src: NSString) -> NSDictionary {
// convert String to NSData
let data = src.dataUsingEncoding(NSUTF8StringEncoding)
var error: NSError?
// convert NSData to 'AnyObject'
let anyObj: AnyObject?
do {
anyObj = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions(rawValue: 0))
} catch let error1 as NSError {
error = error1
anyObj = nil
}
if(error != nil) {
// If there is an error parsing JSON, print it to the console
print("JSON Error \(error!.localizedDescription)")
//self.showError()
return NSDictionary()
} else {
return anyObj as! NSDictionary
}
}
And then, use it like this
if let name = dictionary["name"] as? String {
self.name = name
}
You can use the converted JSON to make an object like this
import Foundation
class Student {
var name="";
init(dictionary: NSDictionary) {
let _NAME = "name"
if let name = dictionary[_NAME] as? String {
self.name = name
}
}
}
oha, well ... search for async network calls for swift. You will find many things.
But yea... Create an NSMutableRequest, init eith the URL, set the method to GET or POST.
Now make:
let task = NSURLSession.sharedSession().dataTaskWithRequest(yourMutableRequest) {
data, response, error in
// do your stuff here
}
task.resume()
This will run asynchron, so you need to think about a way to handle the data. At first your response data is in the variable data this is a type of NSData. You will need this to create your dictionary:
let dictionaryOrArray = NSJSONSerialization.JSONObjectWithData(data, options:.MutableContainers, error: nil)
Maybe you need to put this in a guard or if let statemant.
Now you need to pass the data to the function caller... you can do this in many ways, i prefer success and failure blocks
You call your Request function and you provide a success and failure block. This blocks will do what should happen in the end:
let successBlock:[AnyObject]->Void = { response in
// handle your dict
}
let failureBlock:NSError->Void = { error in
// error handling
}
YourClass.fetchSomething(someURL, parameters: params, requestMethod: method, success : successBlock, failure: failureBlock)
Something like that. In your request block with data, response, error you just do the following:
If error {
failure(error)
return
}
success(dictionaryOrArray)

Cannot parse JSON data correctly

I've been trying to parse this JSON data, but for some reason have not been able to. The code and JSON that I have are below. I want it to show each page in pages and print it to the console. The code works, it just doesn't actually process anything after the if let pages = JSON[] (or so it seems,) because it won't print my for loop or page in pages. Code and JSON is below.
Here's the JSON data I'm trying to parse:
{"43993167":{"summonerId":43993167,"pages":[{"id":54725209,"name":"Jinx","current":false,"slots":[{"runeSlotId":1,"runeId":5245},{"runeSlotId":2,"runeId":5245},{"runeSlotId":3,"runeId":5245},{"runeSlotId":4,"runeId":5245},{"runeSlotId":5,"runeId":5245},{"runeSlotId":6,"runeId":5245},{"runeSlotId":7,"runeId":5245},{"runeSlotId":8,"runeId":5245},{"runeSlotId":9,"runeId":5245},{"runeSlotId":10,"runeId":5317},{"runeSlotId":11,"runeId":5317},{"runeSlotId":12,"runeId":5317},{"runeSlotId":13,"runeId":5317},{"runeSlotId":14,"runeId":5317},{"runeSlotId":15,"runeId":5317},{"runeSlotId":16,"runeId":5317},{"runeSlotId":17,"runeId":5317},{"runeSlotId":18,"runeId":5317},{"runeSlotId":19,"runeId":5289},{"runeSlotId":20,"runeId":5289},{"runeSlotId":21,"runeId":5289},{"runeSlotId":22,"runeId":5289},{"runeSlotId":23,"runeId":5289},{"runeSlotId":24,"runeId":5289},{"runeSlotId":25,"runeId":5289},{"runeSlotId":26,"runeId":5289},{"runeSlotId":27,"runeId":5289},{"runeSlotId":28,"runeId":5337},{"runeSlotId":29,"runeId":5337},{"runeSlotId":30,"runeId":5337}]},{"id":54725210,"name":"support","current":false,"slots":[{"runeSlotId":1,"runeId":5255},{"runeSlotId":2,"runeId":5255},{"runeSlotId":3,"runeId":5255},{"runeSlotId":4,"runeId":5255},{"runeSlotId":5,"runeId":5255},{"runeSlotId":6,"runeId":5255},{"runeSlotId":7,"runeId":5247},{"runeSlotId":8,"runeId":5247},{"runeSlotId":9,"runeId":5247},{"runeSlotId":10,"runeId":5317},{"runeSlotId":11,"runeId":5317},{"runeSlotId":12,"runeId":5317},{"runeSlotId":13,"runeId":5317},{"runeSlotId":14,"runeId":5317},{"runeSlotId":15,"runeId":5317},{"runeSlotId":16,"runeId":5317},{"runeSlotId":17,"runeId":5317},{"runeSlotId":18,"runeId":5317},{"runeSlotId":19,"runeId":5289},{"runeSlotId":20,"runeId":5289},{"runeSlotId":21,"runeId":5289},{"runeSlotId":22,"runeId":5289},{"runeSlotId":23,"runeId":5289},{"runeSlotId":24,"runeId":5289},{"runeSlotId":25,"runeId":5289},{"runeSlotId":26,"runeId":5289},{"runeSlotId":27,"runeId":5289},{"runeSlotId":28,"runeId":5347},{"runeSlotId":29,"runeId":5365},{"runeSlotId":30,"runeId":5365}]},{"id":64389802,"name":"Twisted Fate","current":false,"slots":[{"runeSlotId":1,"runeId":5273},{"runeSlotId":2,"runeId":5273},{"runeSlotId":3,"runeId":5273},{"runeSlotId":4,"runeId":5273},{"runeSlotId":5,"runeId":5273},{"runeSlotId":6,"runeId":5273},{"runeSlotId":7,"runeId":5273},{"runeSlotId":8,"runeId":5273},{"runeSlotId":9,"runeId":5273},{"runeSlotId":10,"runeId":5315},{"runeSlotId":11,"runeId":5315},{"runeSlotId":12,"runeId":5315},{"runeSlotId":13,"runeId":5315},{"runeSlotId":14,"runeId":5315},{"runeSlotId":15,"runeId":5316},{"runeSlotId":16,"runeId":5316},{"runeSlotId":17,"runeId":5316},{"runeSlotId":18,"runeId":5316},{"runeSlotId":19,"runeId":5289},{"runeSlotId":20,"runeId":5289},{"runeSlotId":21,"runeId":5289},{"runeSlotId":22,"runeId":5289},{"runeSlotId":23,"runeId":5289},{"runeSlotId":24,"runeId":5289},{"runeSlotId":25,"runeId":5289},{"runeSlotId":26,"runeId":5289},{"runeSlotId":27,"runeId":5289},{"runeSlotId":28,"runeId":5365},{"runeSlotId":29,"runeId":5365},{"runeSlotId":30,"runeId":5365}]},{"id":69919016,"name":"Ahri","current":false,"slots":[{"runeSlotId":1,"runeId":5273},{"runeSlotId":2,"runeId":5273},{"runeSlotId":3,"runeId":5273},{"runeSlotId":4,"runeId":5273},{"runeSlotId":5,"runeId":5273},{"runeSlotId":6,"runeId":5273},{"runeSlotId":7,"runeId":5273},{"runeSlotId":8,"runeId":5273},{"runeSlotId":9,"runeId":5273},{"runeSlotId":10,"runeId":5316},{"runeSlotId":11,"runeId":5316},{"runeSlotId":12,"runeId":5316},{"runeSlotId":13,"runeId":5316},{"runeSlotId":14,"runeId":5316},{"runeSlotId":15,"runeId":5316},{"runeSlotId":16,"runeId":5316},{"runeSlotId":17,"runeId":5316},{"runeSlotId":18,"runeId":5316},{"runeSlotId":19,"runeId":5289},{"runeSlotId":20,"runeId":5289},{"runeSlotId":21,"runeId":5289},{"runeSlotId":22,"runeId":5289},{"runeSlotId":23,"runeId":5289},{"runeSlotId":24,"runeId":5289},{"runeSlotId":25,"runeId":5289},{"runeSlotId":26,"runeId":5289},{"runeSlotId":27,"runeId":5289},{"runeSlotId":28,"runeId":5357},{"runeSlotId":29,"runeId":5357},{"runeSlotId":30,"runeId":5357}]},{"id":71240898,"name":"Gragas","current":false,"slots":[{"runeSlotId":1,"runeId":5247},{"runeSlotId":2,"runeId":5247},{"runeSlotId":3,"runeId":5247},{"runeSlotId":4,"runeId":5247},{"runeSlotId":5,"runeId":5247},{"runeSlotId":6,"runeId":5247},{"runeSlotId":7,"runeId":5247},{"runeSlotId":8,"runeId":5247},{"runeSlotId":9,"runeId":5247},{"runeSlotId":10,"runeId":5318},{"runeSlotId":11,"runeId":5318},{"runeSlotId":12,"runeId":5318},{"runeSlotId":13,"runeId":5318},{"runeSlotId":14,"runeId":5318},{"runeSlotId":15,"runeId":5318},{"runeSlotId":16,"runeId":5318},{"runeSlotId":17,"runeId":5318},{"runeSlotId":18,"runeId":5316},{"runeSlotId":19,"runeId":5290},{"runeSlotId":20,"runeId":5290},{"runeSlotId":21,"runeId":5290},{"runeSlotId":22,"runeId":5290},{"runeSlotId":23,"runeId":5290},{"runeSlotId":24,"runeId":5290},{"runeSlotId":25,"runeId":5290},{"runeSlotId":26,"runeId":5290},{"runeSlotId":27,"runeId":5290},{"runeSlotId":28,"runeId":5357},{"runeSlotId":29,"runeId":5357},{"runeSlotId":30,"runeId":5357}]},{"id":71240899,"name":"Zac","current":false,"slots":[{"runeSlotId":1,"runeId":5273},{"runeSlotId":2,"runeId":5273},{"runeSlotId":3,"runeId":5273},{"runeSlotId":4,"runeId":5273},{"runeSlotId":5,"runeId":5273},{"runeSlotId":6,"runeId":5273},{"runeSlotId":7,"runeId":5273},{"runeSlotId":8,"runeId":5273},{"runeSlotId":9,"runeId":5273},{"runeSlotId":10,"runeId":5318},{"runeSlotId":11,"runeId":5318},{"runeSlotId":12,"runeId":5318},{"runeSlotId":13,"runeId":5318},{"runeSlotId":14,"runeId":5318},{"runeSlotId":15,"runeId":5318},{"runeSlotId":16,"runeId":5318},{"runeSlotId":17,"runeId":5318},{"runeSlotId":18,"runeId":5325},{"runeSlotId":19,"runeId":5295},{"runeSlotId":20,"runeId":5295},{"runeSlotId":21,"runeId":5295},{"runeSlotId":22,"runeId":5296},{"runeSlotId":23,"runeId":5289},{"runeSlotId":24,"runeId":5289},{"runeSlotId":25,"runeId":5289},{"runeSlotId":26,"runeId":5289},{"runeSlotId":27,"runeId":5289},{"runeSlotId":28,"runeId":5357},{"runeSlotId":29,"runeId":5357},{"runeSlotId":30,"runeId":5357}]},{"id":71240900,"name":"Volibear","current":false,"slots":[{"runeSlotId":1,"runeId":5247},{"runeSlotId":2,"runeId":5247},{"runeSlotId":3,"runeId":5247},{"runeSlotId":4,"runeId":5247},{"runeSlotId":5,"runeId":5247},{"runeSlotId":6,"runeId":5247},{"runeSlotId":7,"runeId":5247},{"runeSlotId":8,"runeId":5247},{"runeSlotId":9,"runeId":5247},{"runeSlotId":10,"runeId":5317},{"runeSlotId":11,"runeId":5317},{"runeSlotId":12,"runeId":5317},{"runeSlotId":13,"runeId":5317},{"runeSlotId":14,"runeId":5317},{"runeSlotId":15,"runeId":5317},{"runeSlotId":16,"runeId":5317},{"runeSlotId":17,"runeId":5317},{"runeSlotId":18,"runeId":5317},{"runeSlotId":19,"runeId":5295},{"runeSlotId":20,"runeId":5295},{"runeSlotId":21,"runeId":5295},{"runeSlotId":22,"runeId":5289},{"runeSlotId":23,"runeId":5289},{"runeSlotId":24,"runeId":5289},{"runeSlotId":25,"runeId":5289},{"runeSlotId":26,"runeId":5289},{"runeSlotId":27,"runeId":5289},{"runeSlotId":28,"runeId":5365},{"runeSlotId":29,"runeId":5365},{"runeSlotId":30,"runeId":5365}]},{"id":71240901,"name":"I AM SMURF","current":false,"slots":[{"runeSlotId":1,"runeId":5273},{"runeSlotId":2,"runeId":5273},{"runeSlotId":3,"runeId":5273},{"runeSlotId":4,"runeId":5273},{"runeSlotId":5,"runeId":5273},{"runeSlotId":6,"runeId":5273},{"runeSlotId":7,"runeId":5273},{"runeSlotId":8,"runeId":5273},{"runeSlotId":9,"runeId":5273},{"runeSlotId":10,"runeId":5317},{"runeSlotId":11,"runeId":5317},{"runeSlotId":12,"runeId":5317},{"runeSlotId":13,"runeId":5317},{"runeSlotId":14,"runeId":5317},{"runeSlotId":15,"runeId":5317},{"runeSlotId":16,"runeId":5317},{"runeSlotId":17,"runeId":5317},{"runeSlotId":18,"runeId":5317},{"runeSlotId":19,"runeId":5298},{"runeSlotId":20,"runeId":5298},{"runeSlotId":21,"runeId":5298},{"runeSlotId":22,"runeId":5298},{"runeSlotId":23,"runeId":5298},{"runeSlotId":24,"runeId":5298},{"runeSlotId":25,"runeId":5298},{"runeSlotId":26,"runeId":5298},{"runeSlotId":27,"runeId":5298},{"runeSlotId":28,"runeId":5357},{"runeSlotId":29,"runeId":5357},{"runeSlotId":30,"runeId":5357}]},{"id":71240902,"name":"Graves","current":true,"slots":[{"runeSlotId":1,"runeId":5245},{"runeSlotId":2,"runeId":5245},{"runeSlotId":3,"runeId":5245},{"runeSlotId":4,"runeId":5245},{"runeSlotId":5,"runeId":5245},{"runeSlotId":6,"runeId":5245},{"runeSlotId":7,"runeId":5245},{"runeSlotId":8,"runeId":5245},{"runeSlotId":9,"runeId":5245},{"runeSlotId":10,"runeId":5317},{"runeSlotId":11,"runeId":5317},{"runeSlotId":12,"runeId":5317},{"runeSlotId":13,"runeId":5317},{"runeSlotId":14,"runeId":5317},{"runeSlotId":15,"runeId":5317},{"runeSlotId":16,"runeId":5317},{"runeSlotId":17,"runeId":5317},{"runeSlotId":18,"runeId":5317},{"runeSlotId":19,"runeId":5290},{"runeSlotId":20,"runeId":5290},{"runeSlotId":21,"runeId":5290},{"runeSlotId":22,"runeId":5290},{"runeSlotId":23,"runeId":5290},{"runeSlotId":24,"runeId":5290},{"runeSlotId":25,"runeId":5290},{"runeSlotId":26,"runeId":5290},{"runeSlotId":27,"runeId":5290},{"runeSlotId":28,"runeId":5337},{"runeSlotId":29,"runeId":5337},{"runeSlotId":30,"runeId":5335}]},{"id":71240903,"name":"Vi","current":false,"slots":[{"runeSlotId":1,"runeId":5245},{"runeSlotId":2,"runeId":5245},{"runeSlotId":3,"runeId":5245},{"runeSlotId":4,"runeId":5245},{"runeSlotId":5,"runeId":5245},{"runeSlotId":6,"runeId":5245},{"runeSlotId":7,"runeId":5245},{"runeSlotId":8,"runeId":5245},{"runeSlotId":9,"runeId":5245},{"runeSlotId":10,"runeId":5317},{"runeSlotId":11,"runeId":5317},{"runeSlotId":12,"runeId":5317},{"runeSlotId":13,"runeId":5317},{"runeSlotId":14,"runeId":5317},{"runeSlotId":15,"runeId":5317},{"runeSlotId":16,"runeId":5317},{"runeSlotId":17,"runeId":5317},{"runeSlotId":18,"runeId":5317},{"runeSlotId":19,"runeId":5290},{"runeSlotId":20,"runeId":5290},{"runeSlotId":21,"runeId":5290},{"runeSlotId":22,"runeId":5295},{"runeSlotId":23,"runeId":5295},{"runeSlotId":24,"runeId":5295},{"runeSlotId":25,"runeId":5290},{"runeSlotId":26,"runeId":5290},{"runeSlotId":27,"runeId":5290},{"runeSlotId":28,"runeId":5335},{"runeSlotId":29,"runeId":5335},{"runeSlotId":30,"runeId":5335}]},{"id":71240904,"name":"Reksai","current":false,"slots":[{"runeSlotId":1,"runeId":5245},{"runeSlotId":2,"runeId":5245},{"runeSlotId":3,"runeId":5245},{"runeSlotId":4,"runeId":5245},{"runeSlotId":5,"runeId":5245},{"runeSlotId":6,"runeId":5245},{"runeSlotId":7,"runeId":5245},{"runeSlotId":8,"runeId":5245},{"runeSlotId":9,"runeId":5245},{"runeSlotId":10,"runeId":5317},{"runeSlotId":11,"runeId":5317},{"runeSlotId":12,"runeId":5317},{"runeSlotId":13,"runeId":5317},{"runeSlotId":14,"runeId":5317},{"runeSlotId":15,"runeId":5317},{"runeSlotId":16,"runeId":5317},{"runeSlotId":17,"runeId":5317},{"runeSlotId":18,"runeId":5317},{"runeSlotId":19,"runeId":5290},{"runeSlotId":20,"runeId":5290},{"runeSlotId":21,"runeId":5290},{"runeSlotId":22,"runeId":5290},{"runeSlotId":23,"runeId":5290},{"runeSlotId":24,"runeId":5290},{"runeSlotId":25,"runeId":5290},{"runeSlotId":26,"runeId":5290},{"runeSlotId":27,"runeId":5290},{"runeSlotId":28,"runeId":5335},{"runeSlotId":29,"runeId":5335},{"runeSlotId":30,"runeId":5335}]}]}}
Here's my code for trying to parse it:
let task = session.dataTaskWithURL(url) { data, response, error in
if let httpResponse = response as? NSHTTPURLResponse {
switch httpResponse.statusCode {
case 200..<300:
if let json = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as? [String : AnyObject] {
println("json working") //this is as far as it will go, won't process the next part
//println(json)
if let pages = json["pages"] as? [[String : AnyObject]] {
println("stat summary working")
for page in pages {
println("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n")
println(page)
}
}
}
default: println("Not Ok")
}
}
}
task.resume()
URL is just the URL that shows the JSON data that I posted above the code.
You're not accessing your json correctly, by that I mean the path you provide in json["pages"] is not a valid one. Look at the data closer; {"43993167":{"summonerId":43993167,"pages"
You have an object, inside it the first thing is another object with the name/key "43993167", under that it has pages. So you would need json["43993167"]["pages"] to access the data you're trying to reach.
That being said, I can tell just by assumption you're dealing with a dictionary of summoner objects where the key is the summonerid and then you're trying to look at their rune page data... A better design would be to deserialize into something that reflects that structure (like a dictionary of summoner objects) then iterate that dictionary.
Ultimately you have something like this;
rootLevelDictionary[]
summoner
summonerId
pages[]
id
name
current
slots[]
runeObject
runeSlotId
runeId
That's the basic structure of your json. If I have time I'll turn it into a valid json-schema but hopefully that is enough to get you unblocked.
Because json["pages"] doesnt exist, its nested inside "43993167".
json["43993167"]["pages"] is what you need
Finally got it to work. Had to change the code a little bit. Here's how it looks now:
let task = session.dataTaskWithURL(url) { data, response, error in
if let httpResponse = response as? NSHTTPURLResponse {
switch httpResponse.statusCode {
case 200..<300:
if let json = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as? NSDictionary, let include = json.objectForKey("\(self.idNumber)") as? NSDictionary {
println("json working")
//println(json)
if let pages = include["pages"] as? [[String : AnyObject]] {
println("stat summary working")
for page in pages {
println("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n")
println(page)
}
}
}
default: println("Not Ok")
}
}
}
task.resume()

Resources