I am getting {"result":"0"} string . The problems is that my serialization function cant serialize it
var err: NSError?
var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves, error: &err) as NSDictionary
if(err != nil) {
println(err!.localizedDescription)
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: '\(jsonStr)'")
}
I am getting answer on console:
Body: Optional({"result":"0"})
Error could not parse JSON: Optional({"result":"0"})
I the function cant serialize it?
This is because your variable 'data' is optional type. You have to either unwrape it. Or use ! sign. But the later is risky as it might have nil also and app will crash. So do this
if let dat = data
{
var err: NSError?
var json = NSJSONSerialization.JSONObjectWithData(dat, options: .MutableLeaves, error: &err) as NSDictionary
}
Related
I am trying to code a login system with jSon. I can receive and parse the results but when i am trying to use values i am receiving fatal errors.
My code:
var request = NSMutableURLRequest(URL: NSURL(string: "http://www.somedomain.com/api/login.php")!)
var session = NSURLSession.sharedSession()
request.HTTPMethod = "POST"
var params:NSDictionary = ["e":"\(email)", "p":"\(passwd)"]
var err: NSError?
request.HTTPBody = NSJSONSerialization.dataWithJSONObject(params, options: NSJSONWritingOptions.allZeros, 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
var strData = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Body: \(strData)")
var err: NSError?
var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves, error: &err) as? NSDictionary
if(err != nil) {
println(err!.localizedDescription)
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: '\(jsonStr)'")
}
else {
if let parseJSON = json {
var success = parseJSON["result"] as? Int
var msg = parseJSON["msg"] as? String
println("Succes: \(success!)") // This works fine i can receive the success variable from json
if success! == 1 { // this line throws error as "fatal error: unexpectedly found nil while unwrapping an Optional value"
// Do something...
} else {
// Do something...
}
}
} else {
let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Error could not parse JSON: \(jsonStr)")
}
}
})
task.resume()
What's the problem with my code? I can not use the values that i received from jSon in my code. I am really confused with the "Optional" thing...
When i use values in println() everything is fine, but when i use the values in code that crashes... By the way it was working fine until today :S
This is the error:
Body: Optional({"result":1,"id":"2","name":"tt","msg":"Login successfull"})
Succes: 1
fatal error: unexpectedly found nil while unwrapping an Optional value
Thanks...
I am new to Xcode and Swift, and I am trying to serialize JSON data from a url using the code below and get the error
'NSJSONReadingOptions' is not convertible to 'NSJSONWritingOptions'
on the line
var jsonResult = NSJSONSerialization.dataWithJSONObject(data, options: NSJSONReadingOptions.MutableContainers, error: nil)!
I cannot see my error, from online sources others use the same code and its works?
let task = session.dataTaskWithURL(loginUrl!, completionHandler: { (data, response, error) -> Void in
if error != nil {
}else {
var jsonResult = NSJSONSerialization.dataWithJSONObject(data, options: NSJSONReadingOptions.MutableContainers, error: nil)!
println(jsonResult)
}
})
task.resume();
Read the docs for dataWithJSONObject. The options parameter needs to be a value from the NSJSONWritingOptions enum, not the NSJSONReadingOptions enum.
But if your goal here is to convert an NSData object to an NSArray or NSDictionary, then the problem is that you are calling the wrong method. You want to use JSONObjectWithData, not dataWithJSONObject.
I am trying to parse JSON result obtained from Playframewordk 1.2 into swift.
Playframework result:
public JsonObject getJson() {
JsonObject jsonObject = new JsonObject();
if (codeJson != null) {
for (String field : codeArticleFields) {
if (codeJson.has(field)) {
jsonObject.add(field, codeJson.get(field));
}
}
}
return jsonObject;
}
view playframework
#{extends 'main.html' /}
#{set title:'Test' /}
#{set 'moreScripts' }
#{/set}
${product?.getJson()}
Here is the code of swift:
func connectProductDatabase() {
let urlString = "http://api.autoidlabs.ch/test/" + "4025089060857"
let url: NSURL = NSURL(string: urlString)!
var request : NSMutableURLRequest = NSMutableURLRequest()
request.URL = url
request.HTTPMethod = "GET"
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue(), completionHandler: {
(response:NSURLResponse!, data: NSData!, error: NSError!) -> Void in
var error: NSError?
if let result = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &error)
as? NSArray {
let dataArray = result[0] as NSArray
println(dataArray)
} else {
let resultString = NSString(data: data, encoding: NSUTF8StringEncoding)
println("Flawed JSON String: \(resultString)")
}
})
println("not connected")
}
As a result I am getting the entire file with all HTML tag. This is because it is not entering into the if statement. (I also tried with options:NSJSONReadingOptions.MutableContainers)
I tried with lot of result found from stackoverflow, but getting the same problem. If I understand well, the playframework view is not really returning a JSON, JsonObject of java is a formatted String as JSON.
How can I solve this problem?
I was able to solve the problem.
Instead of NSArray I used NSDictionary
if let result = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &error)
as? NSDictionary {
and then in playframework I used renderJSON instead of render.
I'm trying to learn Swift and am struggling with understanding a piece about handling JSON and get "fatal error: unexpectedly found nil while unwrapping an Optional value" from using this code:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var webView: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
let urlPath = "http://api.worldweatheronline.com/free/v2/marine.ashx?key=45e8e583134b4371a2fa57a9e5776&format=xml&q=45,-2"
let url: NSURL = NSURL(string: urlPath)!
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url, completionHandler: {data, response, error -> Void in
println("Task completed")
if ((error) != nil) {
println(error)
} else {
var err: NSError?
println("URL: \(url)")
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as NSDictionary
println(jsonResult)
}
})
task.resume()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
The API key I'm using is free so don't worry about using it. The JSON results should look something like this but I am instead greeted with:
Task completed
URL: http://api.worldweatheronline.com/free/v2/marine.ashx?key=45e8e583134b4371a2fa57a9e5776&format=xml&q=45,-2
fatal error: unexpectedly found nil while unwrapping an Optional value
I'm assuming the jsonResult variable is what's causing the problem, but even if I try to force unwrap it (I think that's what I'm doing?) with something like
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as! NSDictionary
it still fails with "expected type after 'as'."
Everything is fail-able here, a website can even return 200 but return nothing, the data can come corrupted, and, in your case, I tried calling the URL you are using and found out, it's actually XML, so... there's your problem?
A more robust approach (assuming that you still want to parse JSON, maybe from another site? The ISS has an open API) is to use the if let to unwrap optionals and then on the else case deal with the errors, rather than ! your way to success.
Here's a very extensive check of everything
task = session.dataTaskWithRequest(NSURLRequest(URL: url), completionHandler: { [unowned self] (data, response :NSURLResponse!, errorRequest) -> Void in
// Check the HTTP Header
if let responseHTTP = response as? NSHTTPURLResponse
{
if responseHTTP.statusCode != 200
{
println("Received status code \(responseHTTP.statusCode)")
return
}
}
else
{
println("Non-HTTP Response received")
return
}
var errorParsing : NSError?
if let JSON = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.allZeros, error: &errorParsing) as? NSDictionary
{
// Do the parsing
}
else
{
println("Error parsing: \(errorParsing)")
}
})
task!.resume()
NSJSONSerialization.JSONObjectWithData... returns an optional NSData?. This means that you can't cast it directly to NSDictionary. To fix the crash you will need to use ?as which means your jsonResult will either be a NSDictionary or nil
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) ?as NSDictionary
In your case, you can safely unwrap the optional by doing this.
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil)
if let jsonResult = jsonResult ?as NSDictionary {
println(jsonResult)
}
How to check Optionals in Swift for nil values?
I'm trying to evaluate if parsing JSON was successful. This should print a error message when invalid json is passed, but fails with EXC_BAD_INSTRUCTION.
func parseJson(data: NSData) {
var error: NSError?
var json: NSDictionary = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &error) as NSDictionary
if let err = error {
println("error parsing json")
return
}
println("json parsed successfully")
}
Try running with valid json (works fine):
parseJson(NSData(data: "{}".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)))
Try with invalid json:
parseJson(NSData(data: "123".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)))
Did I miss the point on working with Optionals?
The crash is happening because JSONObjectWithData returns nil if there's an error. You then try to cast nil to NSDictionary. This works:
func parseJson(data: NSData) {
var error: NSError?
var json : AnyObject! = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &error)
if let err = error {
println("error parsing json")
return
}
println("json parsed successfully")
var jsonDict = json as NSDictionary
}
If you prefer, you can switch the type of var json to NSDictionary? so it directly handles nil. To do this you just need to add a '?' to the "as" keyword as so:
func parseJson(data: NSData) {
var error: NSError?
var json: NSDictionary? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &error) as? NSDictionary
if let err = error {
println("error parsing json")
return
}
// unwrap the optional value
if let jsonDictionary = json {
println("json parsed successfully")
// use the dictionary
}
}
I restructured your code a bit:
func parseJson(data: NSData) {
var error: NSError?
var json: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &error)
if let jsonDict: NSDictionary = json as? NSDictionary{
println("json parsed successfully")
//do something with the nsdictionary...
}
else{
println("error parsing json")
}
}
parseJson(NSData(data: "{}".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)))
parseJson(NSData(data: "123".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)))
The problem wasn't with your if code, but making json an NSDictionary when it isn't one when the method fails. Also, this code now checks if an NSDictionary was returned instead of checking for the error itself.
NSJSONSerialization.JSONObjectWithData returns an optional value that has been implicitly unwrapped, which means that the return value could be nil. In the invalid JSON case, a nil optional type was returned. So, your var json must also be an optional type since it could be nil. Further more, if var json is optional type then you must downcast it as optional by adding ? next to as. This is the final result
var json: NSDictionary? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &error) as? NSDictionary
I was getting fatal error: unexpectedly found nil while unwrapping an Optional value until I made the NSDictionary type casting optional, e.g. as? NSDictionary instead of as Dictionary