NSJSONSerialization Failing - ios

I am making a simple request to the Flickr API. I know that the request URL is correct and that the URL task returns data. However, when I try:
let jsonObject: AnyObject! = try NSJSONSerialization.JSONObjectWithData(data, options: [])
in a do, catch block, the operation fails but doesn't crash the app. I have tried changing the options to MutableContainers and AllowFragments but nothing seems to work.

Take the data and convert it to a string like this:
let responseString = String(data: data, encoding: NSUTF8StringEncoding)
Then paste that through a validator like jsonlint.com to see if you're actually getting valid JSON.
I suspect you aren't getting a valid HTTP response from the API, and so maybe you're getting HTML back (or plain text) that describes the error?

Related

JSON File has É in it. When I download from feed on server data returned can't be parsed. Same data in local copy in projects works downloadis?

When downloading data from server JSON feed, I can't parse the data received as the data has this É . I am running in swift4. I create a copy the data file into my project locally and the parsing works, using JSONDecoder().decode with the data structure no problem.
I believe it has something to do with how I create my request object or session config but I am not too versed in this area.
I think its from charset=ISO-8859-1
don't know how to use this in my request/session to handle this character
spent a lot of time on this not sure where to look
I found the solution to my problem.
All I needed to do was convert the data from charset=ISO-8859-1 to utf8
I created a NSString out of the data returned from the response.
let responseString = NSString(data: data!, encoding:
String.EncodingConversionOptions.allowLossy.rawValue)
let s = responseString! as String
let d = Data(s.utf8)
then I was able to pass the converted Data object into the JSONDescoder()
now I am new to programming so if there is a better way I could have done this I would like feedback because String.EncodingConversionOptions.allowLossy.rawValue was just through trial and error.
thank you
Peter

Why is one version of my http POST body not working?

I am trying to send something to an API using POST. The post body is made up of x 2 properties.
If I create the post body as one long string:
let postBody = "ministryId=nameOfMinistryHere&personId=1005" and then encode the string as follows urlRequest.httpBody = postBody.data(using: String.Encoding.utf8) it works perfectly.
But I am trying to create the post as a dictionary and then pass it to the API, but can't get it to work.
let postBody = ["ministryId":"nameOfMinistry", "personId":"1005"]
do {
try urlRequest.httpBody = JSONSerialization.data(withJSONObject: postBody, options: .prettyPrinted)
} catch {
print("problems serializing data")
}
When I use the latter option I am getting a 400 error from the server.
What am I missing?
Thanks in advance.
URLComponents is the class for dealing with multiple parameters. Code snippet:
let postBody = ["ministryId":"nameOfMinistry", "personId":"1005"]
let urlComponents = URLComponents(string: myURL)
let urlRequest = URLRequest(url: urlComponents.url!)
// transform the dictionary into queryItems
urlComponents.queryItems = postBody.map { URLQueryItem(name: $0, value: $1) }
urlRequest.httpBody = urlComponents.percentEncodedQuery?.data(using: String.Encoding.utf8)
thecloud_of_unKnowing answer to your comment as it was long i am posting it here -:
HTTP headers can be mainly classified into two types: HTTP Request Header Whenever you type a URL into the address bar and try to access it, your browser sends an HTTP request to the server. The HTTP request header contains information in a text-record form, which includes particulars such as the type, capabilities and version of the browser that generates the request, the operating system used by the client, the page that was requested, the various types of outputs accepted by the browser, and so on. HTTP Response Header Upon receiving the request header, the Web server will send an HTTP response header back to the client. An HTTP response header includes information in a text-record form that a Web server transmits back to the client's browser. The response header contains particulars such as the type, date and size of the file sent back by the server, as well as information regarding the server.SO you are just sending extra information to your server to let it know what kind of request it will accept.
Content-type: application/json; charset=utf-8 designates the content to be in JSON format, encoded in the UTF-8 character encoding. Designating the encoding is somewhat redundant for JSON, since the default (only?) encoding for JSON is UTF-8. So in this case the receiving server apparently is happy knowing that it's dealing with JSON and assumes that the encoding is UTF-8 by default, that's why it works with or without the header.
Simply make a dictionary as follows:
let jsonBody = ["username": email, "password": password]
Then you can do something like this:
let request = NSMutableURLRequest(url: NSURL(string: "YOUR URL") as URL)
request.httpBody = try! JSONSerialization.data(withJSONObject: jsonBody, options: .prettyPrinted)
Hope that helps!

How to set body type to JSON in Alamofire?

I'm working online with different people from different projects who take care of backend API webservice. Usually I don't have problems with sending and receiving JSON, but this time, I can't seem to be able to send JSON properly to the server.
Usually I use Alamofire to receive and send JSON message, and the usual call go like this:
let param = populateParamWithDictionary();
let url = "https://www.example.com";
Alamofire.request(.POST, url, parameters: param, headers: nil)
.responseJSON { response in {
// take care of response here
}
But this time, I got project which the backend programmer requires me to use OAuth v2. So, let's say I've develop a function which already take care of getting the access_token string. The function now become like this:
let param = populateParamWithDictionary();
let url = "https://www.example.com";
let headers : Dictionary<String, String> = [
"Content-Type":"application/json",
"Authorization":"Bearer \(access_token)"
];
Alamofire.request(.POST, url, parameters: param, headers: headers)
.responseJSON { response in {
// take care of response here
}
But instead of the result, I get 400 bad request error. I also even try this:
let param = populateParamWithDictionary();
let url = "https://www.example.com";
let headers : Dictionary<String, String> = [
"Content-Type":"application/json",
"Authorization":"Bearer \(access_token)"
];
Alamofire.request(.POST, url, parameters: param, encoding: ParameterEncoding.JSON, headers: headers)
.responseJSON { response in {
// take care of response here
}
But the result is even worse. This is what I get when I print the response.
FAILURE: Error Domain=NSURLErrorDomain Code=-1017 "cannot parse
response" UserInfo={NSUnderlyingError=0x7fbb505788f0 {Error
Domain=kCFErrorDomainCFNetwork Code=-1017 "(null)"
UserInfo={_kCFStreamErrorCodeKey=-1, _kCFStreamErrorDomainKey=4}},
NSErrorFailingURLStringKey=http://lfapp.learnflux.net/v1/me,
NSErrorFailingURLKey=http://lfapp.learnflux.net/v1/me,
_kCFStreamErrorDomainKey=4, _kCFStreamErrorCodeKey=-1, NSLocalizedDescription=cannot parse response}
But the request works if I use REST client, by setting the headers to have the authentication and Content-Type, and have the parameters to be written as plain Content, e.g. in plain API in the body content.
How can I fix this?
EDIT: The part with the access token is already clear. The access token works. I can call an API successfully if the API doesn't requires any parameters (maybe because on the server, the code doesn't bother to even check or validate the body at all because it doesn't need anything from there, hence no error raised). The problem is when I make a request which needs any parameters.
The error you have is probably because of encoding: ParameterEncoding.JSON in the request. Try to change it to encoding: .URLEncodedInURL. If this doesn't help you, do add your parameters to the question and if you´re make a request to get the token do the following:
if let access_token = json["access_token"]!{
// Make the request here when you know that you have your token
}

How to identify a JSON object using swift and xctest framework?

Using NSJSONSerialization.JSONObjectWithData(..) we can create a JSON object. But is it possible to identify the object type ie. is it a JSON object or not.
I was just trying to check using Swift and XCTestFramework. I tried different ways but no solution still?
Note: After creation of JSON object, I can get the values and can also check the values. XCTest Framework is working fine to test those type of things. But, I stuck to identify the object type.
Anybody has any idea how to identify the JSON object programmatically using Swift and XCTest framework
Update: For example, for a website testing we can do the following:
if let HTTPResponse = response as? NSHTTPURLResponse,
responseURL = HTTPResponse.URL,
MIMEType = HTTPResponse.MIMEType
{
XCTAssertEqual(responseURL.absoluteString, URL.absoluteString, "HTTP response URL should be equal to original URL")
XCTAssertEqual(HTTPResponse.statusCode, 200, "HTTP response status code should be 200")
XCTAssertEqual(MIMEType, "text/html", "HTTP response content type should be text/html")
} else {
XCTFail("Response was not NSHTTPURLResponse")
}
Is something possible like above for JSON?
If you get a valid string within your NSData parameter, but that String is not a valid JSON object, then the parser will throw an error. As from the documentation:
If an error occurs, upon return contains an NSError object that describes the problem.
So check if the object returned is actually an NSError. If you don't get an error, then I would safely assume that the object is indeed a valid JSON object.

XCODE Swift Replacing HTTP-Get App-ID with a space

Sup dudes,
Working on creating a Bing Image Search API for Swift. My problem is that my app key contains '+' and '/' so when I make a request, I'm getting back because it seems that it treats '+' and '/' as spaces. It should treat everything before the query as a regular character, right?
Any idea how to fix this request so it doesn't screw up my AppID?
App ID Example:
"aaaaaa/aaaaaa+baaaaa/asdf="
Response (Formatting is off, but it is in fact a space between the a's)
{"SearchResponse":{"Version":"2.2","Query":{"SearchTerms":"sushi"},"Errors":
[{"Code":1002,"Message":"Parameter has invalid
value.","Parameter":"SearchRequest.AppId","Value":"aaaaaa\u002faaaaaa
baaaaa\u002fasdf\u003d","HelpUrl":"http\u003a\u002f\u002fmsdn.microsoft.com\u002fen-
us\u002flibrary\u002fdd251042.aspx"}]}}
Code for get request (works perfectly):
let url = NSURL(string: "http://api.bing.net/json.aspx?Appid="+AccountKey+"&query="+query+"&sources=Image");
let task = NSURLSession.sharedSession().dataTaskWithURL(url) {(data, response, error) in
println(NSString(data: data, encoding: NSUTF8StringEncoding))
}
task.resume()
Forgot to mention, I got frustrated and tried it out in C# and it works flawlessly. New to Swift (obviously)
Edit: Added URL string to Get Request code sample above.

Resources