Swift: JSON file from URL instead of local - json

Right now I have this:
let path : String = NSBundle.mainBundle().pathForResource("jsonFile", ofType: "json") as String!
let jsonData = NSData(contentsOfFile: path) as NSData!
let readableJSON = JSON(data :jsonData, options: NSJSONReadingOptions.MutableContainers, error: nil)
But I want to receive the file from a url, and not have it in my app.

You need to read through some of apple docs: NSURLConnection and NSURLSession
Here is a quick solution for how to achieve this though.
func fetchDetailsFromServer() {
let urlPath = "Server URL to Fetch JSON"
let url = NSURL(string: urlPath)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url!, completionHandler: {data, response, error -> Void in
println("Task completed")
if(error != nil) {
// If there is an error in the web request, print it to the console
println(error.localizedDescription)
}
var err: NSError?
if let jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as? NSDictionary {
if(err != nil) {
// If there is an error parsing JSON, print it to the console
println("JSON Error \(err!.localizedDescription)")
}
// Use your jsonResult appropriately here
}
})
// The task is just an object with all these properties set
// In order to actually make the web request, we need to "resume"
task.resume()
}

Related

response Data is nil

I am getting response data nil.
func fetchSinglePageData() {
var response: NSData?
var errors: NSError?
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
response = NSData(contentsOfFile:"url...?project_id=(self.projectID)&project_page=Request", options: NSDataReadingOptions(0), error: &errors)
print("LatestURL Single page:(response)")
if response == nil {
var alertview = UIAlertView(title: "Network Error", message: "Data not received due to network connection.Try again...", delegate: self, cancelButtonTitle: "Ok")
alertview.show()
}
else{
let jsonDict: NSDictionary = NSJSONSerialization.JSONObjectWithData(response!, options: nil, error: &errors) as NSDictionary
print("JSON Response Single page:(jsonDict)")
var statuses = [NSObject : AnyObject]()
self.lblstartTime?.text = jsonDict["start_time"] as? String
self.lblcurrentStage?.text = jsonDict["current_stage"] as? String
self.lblcompletionTime?.text = jsonDict["completion_time"] as? String
self.lblManager?.text = jsonDict["manager"] as? String
}
})
}
project_id is string which is recevied from presvious page which is correctly working.
In swift 3
//make a url request
let urlString = "your_url"
let urlRequest = URLRequest.init(url: URL.init(string: urlString)!, cachePolicy: .reloadIgnoringCacheData, timeoutInterval: 50)
//create a session
let session = URLSession.shared
let task = session.dataTask(with: request) { (data, urlResponse, error) in
if error != nil{
//handle error
return
}else{
if let responseData = data{
let jsonDict = try JSONSerialization.jsonObject(with: responseData, options: [])as? [String:Any]
//handle your response here
}
}
}
task.resume()
In swift 2.2
let urlString = "your_url"
let request = NSURLRequest(URL: NSURL(string: urlString)!, cachePolicy: .ReloadIgnoringLocalCacheData, timeoutInterval: 50)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request) { (data, response, error) in
if error != nil{
//handel error
print(error!.localizedDescription)
return
}
if let responseData = data{
do{
if let jsonDict = try NSJSONSerialization.JSONObjectWithData(responseData, options: [])as? [String:Any]{
//you have data in json dict
}
}catch{
print("error in parsing response")
return
}
}
}
task.resume()
func singlePageData(){
var errors: NSError?
let urlString = "xyz.com"
print("URL RESPONSE \(urlString)")
let request = NSURLRequest(URL: NSURL(string: urlString), cachePolicy: .ReloadIgnoringLocalCacheData, timeoutInterval: 50)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(request) { (data, response, error) in
if error != nil{
//handel error
print(error!.localizedDescription)
var alertview = UIAlertView(title: "Network Error", message: "Data not received due to network connection.Try again...", delegate: self, cancelButtonTitle: "Ok")
alertview.show()
return
}
if let responseData = data{
var jsonDict: NSDictionary = NSJSONSerialization.JSONObjectWithData(responseData, options: NSJSONReadingOptions.MutableContainers, error: &errors) as NSDictionary!
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
println("Json dict value \(jsonDict)")
self.lblprojectName?.text = jsonDict["name"] as? String
println("lblprojectName: \(self.lblprojectName?.text)")
self.lblstartTime?.text = jsonDict["start_time"] as? String
println("lblstartTime : \(self.lblstartTime?.text)")
self.lblcurrentStage?.text = jsonDict["current_stage"] as? String
println("lblcurrentStage : \(self.lblcurrentStage?.text)")
self.lblcompletionTime?.text = jsonDict["completion_time"] as? String
println("lblcompletionTime : \(self.lblcompletionTime?.text)")
self.lblManager?.text = jsonDict["manager"] as? String
})
}
}
task.resume()
}
This is my answer as per Jitendra Solanki answer i have made changes to code and it is now working in Swift 1.2
After a quick look, maybe \ missing:
NSData(contentsOfFile:"url...?project_id=\(self.projectID)&project_page=Request"
In this line:
response = NSData(contentsOfFile:"url...?project_id=(self.projectID)&project_page=Request", options: NSDataReadingOptions(0), error: &errors)
you have project_id=(self.projectID), to use interpolation you should instead have project_id=\(self.projectID)
I would suggest that you separate the code to generate your full URL, then print the URL to the console and ensure that it is what you would expect.
Then you can visit the url yourself and check to see what the server returns, then once you know you have the correct URL and response you can then work to deserialise the response
EDIT: updated with URLSession (Swift 3 version)
let defaultSession = URLSession(configuration: URLSessionConfiguration.default)
var dataTask: URLSessionDataTask?
let projectID = 12
let url = URL(string: "http://phpyouth.com/clients/halfpricedgrannyflats/app/app_response.php?project_id=\(projectID)&project_page=Request")
dataTask = defaultSession.dataTask(with: url!) {
data, response, error in
if let error = error {
print(error.localizedDescription)
} else if let httpResponse = response as? HTTPURLResponse {
if httpResponse.statusCode == 200 {
if let responseData = data {
if let json = try? JSONSerialization.jsonObject(with: responseData, options: .allowFragments) as? [String:AnyObject] {
print(json)
}
}
}
}
}
dataTask?.resume()

How to change JSON POST request to handle HTTPS

Below is my login function. It's a JSON POST request and before, when the URL was http, it worked flawlessly. I attached a JSON filled with the username/password of the user. Today we added a SSL Certificate and after switching the URL to https, it produced this error:
NSURLConnection/CFURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9843)
I'm not really sure what's going on. I typed that error into google and didn't get any where. I appreciate any help, thank you!
func login(params : Dictionary<String, String>, url : String, postCompleted : (succeeded: Bool, msg: String) -> ()) {
var request = NSMutableURLRequest(URL: NSURL(string: url)!)
var session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
var err: NSError?
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: nil, error: &err)
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
if response != nil {
if response.isKindOfClass(NSHTTPURLResponse) {
httpResponse = response as NSHTTPURLResponse
if let authorizationID = httpResponse.allHeaderFields["Authorization"] as String! {
Locksmith.saveData(["id":authorizationID], forUserAccount: currentUser, inService: "setUpAuthorizationId")
}
else {
println("Failed")
}
}
}
var err: NSError?
var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves, error: &err) as? NSDictionary
// Did the JSONObjectWithData constructor return an error? If so, log the error to the console
if(err != nil) {
println(err!.localizedDescription)
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: '\(jsonStr!)'")
postCompleted(succeeded: false, msg: "Error")
}
else {
// The JSONObjectWithData constructor didn't return an error. But, we should still
// check and make sure that json has a value using optional binding.
if let parseJSON = json {
// Okay, the parsedJSON is here, let's get the value for 'success' out of it
if let status = parseJSON["status"] as? String {
if let extractData = parseJSON["data"] as? NSDictionary {
let extractUserId:Int = extractData["id"] as Int
userId = extractUserId
}
if status == "success" {
postCompleted(succeeded: true, msg: "Logged in.")
} else {
let failMessage = parseJSON["message"] as? String
postCompleted(succeeded: false, msg: failMessage!)
}
}
return
}
else {
// Woa, okay the json object was nil, something went worng. Maybe the server isn't running?
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: \(jsonStr)")
postCompleted(succeeded: false, msg: "Error")
}
}
})
task.resume()
}
Using This awesome article I was able to fix my problem. All I needed to do was add:
NSObject, NSURLSessionDelegate, NSURLSessionTaskDelegate
after my class name, and then add these two delegates:
func URLSession(session: NSURLSession,
didReceiveChallenge challenge:
NSURLAuthenticationChallenge,
completionHandler:
(NSURLSessionAuthChallengeDisposition,
NSURLCredential!) -> Void) {
completionHandler(
NSURLSessionAuthChallengeDisposition.UseCredential,
NSURLCredential(forTrust:
challenge.protectionSpace.serverTrust))
}
func URLSession(session: NSURLSession, task: NSURLSessionTask, willPerformHTTPRedirection response: NSHTTPURLResponse, newRequest request: NSURLRequest, completionHandler: (NSURLRequest!) -> Void) {
var newRequest : NSURLRequest? = request
println(newRequest?.description);
completionHandler(newRequest)
}
after that in my actual request I just needed to change:
var session = NSURLSession.sharedSession()
to:
var configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
var session = NSURLSession(configuration: configuration, delegate: self, delegateQueue:NSOperationQueue.mainQueue())
hope this helps someone!!

Get JSON data function - Address noch reachable - NSURLErrorDomain error -1002

I have a function to retrieve JSON data from an certain ip address.
if the ip is not reachable, xcode gives me following error at
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as NSDictionary
The operation couldn’t be completed. (NSURLErrorDomain error -1002.) fatal error: unexpectedly found nil while unwrapping an Optional value
How can I check, if jsonResult is valid or if ip-address is valid?
func getJsonData() {
let urlAsString = NSUserDefaults.standardUserDefaults().objectForKey("ipAddress") as String
let url: NSURL = NSURL(string: urlAsString)!
let urlSession = NSURLSession.sharedSession()
let jsonQuery = urlSession.dataTaskWithURL(url, completionHandler: { data, response, error -> Void in
if (error != nil) {
println(error.localizedDescription)
}
var err: NSError?
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as NSDictionary
if (err != nil) {
println("JSON Error \(err!.localizedDescription)")
}
//Display Data
dispatch_async(dispatch_get_main_queue(), {
self.label.text = String(format: "%.3f", (jsonResult["pwr"] as Float!)/1000)
})
})
jsonQuery.resume()
}
Thanks!
if (error != nil) {
println(error.localizedDescription)
}
It's not enough to print an error to debugger console. The error must be handled. Ask yourself - what do you want to do if there is no internet connection? Do you want to display an error to the user? Try to send the request again?
The basic fact is that if there was an error, you cannot continue and parse the data. The data is not there, it was not loaded. If you try to parse the data (which is nil), your app will crash.
if (error != nil) {
//XXX: display error to the user, e.g. using an alert
return; //return immediately, don't proceed to parsing.
}
Create a method like below to check valid url.
func validateUrl (stringURL : NSString) -> Bool {
var urlRegEx = "((https|http)://)((\\w|-)+)(([.]|[/])((\\w|-)+))+"
let predicate = NSPredicate(format:"SELF MATCHES %#", argumentArray:[urlRegEx])
var urlTest = NSPredicate.predicateWithSubstitutionVariables(predicate)
return predicate.evaluateWithObject(stringURL)
}
And then update your method. Add a line to call validate url method.
func getJsonData() {
let urlAsString = NSUserDefaults.standardUserDefaults().objectForKey("ipAddress") as String
var isValidURL = validateUrl(urlAsString)
if (!isValidURL) {
// Return from here. URL is invalid
return
}
let url: NSURL = NSURL(string: urlAsString)!
let urlSession = NSURLSession.sharedSession()
let jsonQuery = urlSession.dataTaskWithURL(url, completionHandler: { data, response, error -> Void in
if (error != nil) {
println(error.localizedDescription)
}
var err: NSError?
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as NSDictionary
if (err != nil) {
println("JSON Error \(err!.localizedDescription)")
}
//Display Data
dispatch_async(dispatch_get_main_queue(), {
self.label.text = String(format: "%.3f", (jsonResult["pwr"] as Float!)/1000)
})
})
jsonQuery.resume()
}

Unable to parse JSON from the HTTP response

Why am I unable to parse JSON from the HTTP response via the following code?
if let url = NSURL(string: "https://2ch.hk/b/threads.json") {
let task = NSURLSession.sharedSession().dataTaskWithURL(url) {
(data, response, error) in
var jsonError: NSError?
let jsonDict = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &jsonError) as [String: AnyObject]
if jsonError != nil {
return
}
// ...
}
task.resume()
}
Output
fatal error: unexpectedly found nil while unwrapping an Optional value
What am I doing wrong? How can I fix it?
Thanks in advance.
This is a bit late.... but I think you are trying to parse the error as well so add an else part and and the dictionary to be serialized will only be parsed if there is the data ... your code can be modified as follows
if let url = NSURL(string: "https://2ch.hk/b/threads.json") {
let task = NSURLSession.sharedSession().dataTaskWithURL(url) {
(data, response, error) in
if (jsonError != nil) {
return
} else {
var jsonError: NSError?
let jsonDict = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &jsonError) as [String: AnyObject]}
// ...
}
task.resume()
}

Get JSON in Swift

This is my code to get JSON, and it's work with this url I found on an other questions : http://binaenaleyh.net/dusor/.
But, when I use it with this url : http://www.netcampus.fr/api/schools, it didn't work at all. I have an error who said : "exc_breakpoint (code=exc_i386_bpt subcode=0x0)"
Is my code wrong, or is it the JSON data ?
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var myData:NSData = getJSON("http://www.netcampus.fr/api/schools")
println(myData) // show me data
var myDict:NSDictionary = parseJSON(myData)
println(myDict)
}
func getJSON(urlToRequest: String) -> NSData{
return NSData(contentsOfURL: NSURL(string: urlToRequest))
}
func parseJSON(inputData: NSData) -> NSDictionary{
var error: NSError?
var boardsDictionary: NSDictionary = NSJSONSerialization.JSONObjectWithData(inputData, options: NSJSONReadingOptions.MutableContainers, error: &error) as NSDictionary // error here
return boardsDictionary
}
}
Your parseJSON method crashes when parsing the second JSON. NSJSONSerialization maps its contents to an array and you are expecting a dictionary:
var boardsDictionary: NSDictionary = NSJSONSerialization.JSONObjectWithData(inputData, options: NSJSONReadingOptions.MutableContainers, error: &error) as NSDictionary // error here
As #reecon pointed out ,your code should be like this
//JSON Parsing
func JSONParsingSample() {
var myData:NSData = getJSON("http://www.netcampus.fr/api/schools")
//println(myData) // show me data
var myDict:NSArray = parseJSON(myData)
println(myDict)
}
func getJSON(urlToRequest: String) -> NSData{
return NSData(contentsOfURL: NSURL(string: urlToRequest))
}
func parseJSON(inputData: NSData) -> NSArray{
var error: NSError?
var boardsDictionary: NSArray = NSJSONSerialization.JSONObjectWithData(inputData, options: NSJSONReadingOptions.MutableContainers, error: &error) as NSArray
return boardsDictionary
}
//end
let urlString = "webAPI"
var request = URLRequest(url: URL(string: urlString)!)
let session = URLSession.shared
request.httpMethod = "GET"
session.dataTask(with: request)
{
data, response, error in
if error != nil
{
print(error!.localizedDescription)
return
}
do
{
let jsonResult: NSDictionary? = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers) as? NSDictionary
self.dict = jsonResult as! NSMutableDictionary
print("Synchronous\(jsonResult)")
DispatchQueue.main.async
{
let url = URL(string: ((((self.dict.value(forKey: "sources") as! NSArray).object(at: 5) as! NSDictionary).value(forKey: "urlsToLogos") as? NSDictionary)?.value(forKey: "small") as? String)!)
let data = try? Data(contentsOf: url!)
}
}
catch
{
print"error"
}
}.resume()