Not able to read JSON from service - objective-c

I am implementing forget password service in which I would pass an email address and it would return JSON to acknowledge about the sent email. The issue is that I am unable to read the response string in json, and my exception message is shown that data parameter is nil, but if I view the url in my web browser the service looks fine as mentioned below.
my code is:
NSURL *url = [LokalmotionCommonTask getURLForgotPassword:emailFieldTxt.text];
NSData* data = [NSData dataWithContentsOfURL: url];
#try {
NSError* error;
NSDictionary* jsonDict = [NSJSONSerialization
JSONObjectWithData:data //1
options:0
error:&error];
NSLog(#"%#", [jsonDict objectForKey:#"response"]);
}
#catch (NSException *exception) {
NSLog(#"forgot password exception: %#: %#", [exception name], [exception reason]);
}
and the service response I get in my web browser is like this:
{"status":400,"response":"Your request to change password is already sent. Please check your email."}
Exception:
forgot password exception: NSInvalidArgumentException: data parameter is nil

in Objective-C exceptions are only used for fatal errors, not recoverable errors. Instead just check for nil data:
If you need to know what was the reason for failure, use:
NSError* error;
NSURL *url = [LokalmotionCommonTask getURLForgotPassword:emailFieldTxt.text];
NSData* data = [NSData dataWithContentsOfURL: url options:NULL error:&error];
if (data) {
NSDictionary* jsonDict = [NSJSONSerialization
JSONObjectWithData:data //1
options:0
error:&error];
NSLog(#"%#", [jsonDict objectForKey:#"response"]);
}
else {
NSLog(#"forgot password error, %#", [error localizedFailureReason]);
}
There is a naming convention error: getURLForgotPassword:
A method name that begins with "get" implies that there will be a return by reference parameter. Better to just name the method: forgotPasswordURL:
These two things, exceptions and accessors prefixed with get are a basic difference from Jave.

There error says data parameter is nil. So the variable you pass for the JSON-date probably is nil.
[NSData dataWithContentsOfURL:url] probably returns nil since an error occured. Try logging that.
Also, even if it is only a small file you request, I would go for an asynchronous request in order not to block the UI.

i was facing the same problem, problem was that i have given extra space in the url string that was url string #" http:...." corrected it by removing space in the start of url string #"https:...."

Solved that by fixing service URL, my url was not encoded and had spaces inline

Related

Sending Xcode data to JSON

I am fairly new to xcode but I currently have an app that will send data to a sql database but I know it has to go through JSON first.
Say my app is simply a text box where a user enters a name and submits. How would I turn that data into JSON? What would the syntax look like?
https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSJSONSerialization_Class/
If you are sending the data through a network, then look into AFNetworking.
(added in response to a comment)
NSString *jsonFromObject(id object)
{
NSError* error = nil;
NSData* jsonData = [NSJSONSerialization dataWithJSONObject: object options: 0 error: &error];
if (error) {
NSLog(#"error creating json string: %#", error);
}
return [[NSString alloc] initWithData: jsonData encoding: NSASCIIStringEncoding];
}

Issue with parsing JSON data

I am trying to convert a string into a json object and am unsure why this is not working. When I nslog the output I am told that urldata is not valid for json serialization however when looking at the string it looks to me like valid json. I have also tried encoding it to an utf8 however it still won't serialize. Am I missing something here? - Note unnecessary code omitted from post.
Get request
urlData = [NSURLConnection sendSynchronousRequest:urlRequest
returningResponse:&response
error:&error];
NSDictionary *tempDict = [NSDictionary alloc];
Parsing
if ([NSJSONSerialization isValidJSONObject:urlData] ) {
NSLog(#"is valid");
tempDict = [NSJSONSerialization JSONObjectWithData:urlData kniloptions error:&error];
}
NSLog(#"is not valid");
Definition:
isValidJSONObject:
Returns a Boolean value that indicates whether a given object can be converted to JSON data.
As you are already mentioning in your question, isValidJSONObject
returns a Boolean value that indicates whether a given object can be
converted to JSON data
In your case, you don't want to create JSON data, but instead create a dictionary out of JSON data. :
tempDict = [NSJSONSerialization JSONObjectWithData:urlData
options:NSJSONReadingMutableContainers
error:&error];
if (!tempDict) {
NSLog(#"Error parsing JSON: %#", error);
}

JSON Payload doesnt seem to be sending

My problem I'm pretty positive is simple, I must just be missing something.. just not sure what.
I can send GET and POST for granular elements (this=that kind of stuff), but a web service call I need to send data too, takes a raw JSON block, with no "key"
Heres the method I wrote:
-(NSData *)execute {
// Smart Chooser ?
if(PostData.count >0 || Payload != nil)
[self setMethod:UPLINK_METHOD_POST];
else
[self setMethod:UPLINK_METHOD_GET];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:self.connectionUrl
cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData
timeoutInterval:10];
if([UPLINK_METHOD_GET isEqualToString:self.connectionMethod])
[request setHTTPMethod:#"GET"];
else
[request setHTTPMethod:#"POST"];
NSString *gData = [self compileGetData];
NSString *pData = [self compilePostData];
// if we have get data, set it into the URL string
if(GetData.count > 0) {
[self setURLWithString:[[self.connectionUrl absoluteString] stringByAppendingString:[#"?" stringByAppendingString:gData]]];
[request setURL:self.connectionUrl];
}
// if we have post data, set it in the body
if(PostData.count > 0) {
const char *bytes = [[NSString stringWithString:pData] UTF8String];
[request setHTTPBody:[NSData dataWithBytes:bytes length:strlen(bytes)]];
}
// Override any post data if a payload is already defined.
if(Payload != nil) {
[request setHTTPBody:[Payload dataUsingEncoding:NSUTF8StringEncoding]];
}
NSLog(#"URL : %#", request.URL);
NSURLResponse *response;
NSError *err;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&err];
if(err != nil)
NSLog(#"here was an error: %#", err);
return responseData;
}
-(NSDictionary *)executeAsJSON
{
NSData *responseData = [self execute];
NSError *e;
return [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableContainers error:&e];
}
Ok SO, the way this thing works, is that it automatically sets whether the request is POST or GET depending on the data provided in the GetData, PostData, and Payload vars.
The request is GET by default, but turns into POST if PostData or Payload have anything in them.
The compileGetData and compilePostData mostly just bring back formatted strings with arrays of information combined, nothing special there.
But thats not where the problem is.
See, "Payload" overrides anything "PostData" had in it. If you had provided PostData elements into the class, it would just be overridden by a provided Payload if that does exist.
I needed to provide this to demonstrate the "workarea" as it exists right now, its not linearly provided information.
This is the area of interest:
// Override any post data if a payload is already defined.
if(Payload != nil) {
//const char *plbytes = [[NSString stringWithString:Payload] UTF8String]; // this didn't work
[request setHTTPBody:[Payload dataUsingEncoding:NSUTF8StringEncoding]]; // inline, doesn't work either
}
When I say "doesnt work", what I mean is, im getting back an error JSON array from the webservice that basically means "hey, wheres the payload?". If the request is not POST it comes back as a general error, so thats all working, the URL is then obviously correct.
I've used RESTConsole for Chrome to test the webservice to make sure its working properly, and it does.
I've also checked through the debugger the exact payload im sending, i copy+pasted that into RESTConsole, and it works there.
I'm.. honestly at a loss here...
Try using a web proxy like Charles or Wireshark (I personally preferr Charles due to it's ease of use, it's a 30-day trial though) and monitor the request you make from RESTConsole and the one you make from your app and see if they look the same.
Check any headers, line returns and anything else that looks different.
That's the best I can think of to start with

EXC_BAD_ACCESS after executing an asynchronous URL request

I am trying to execute an asynchronous URL request:
NSURLRequest* request=[NSURLRequest requestWithURL: [NSURL URLWithString: #"http://www.youtube.com/"]];
NSOperation* operation=[NSOperation new];
NSOperationQueue* queue=[NSOperationQueue new];
[operation setCompletionBlock: ^()
{
}];
[queue addOperation: operation];
[NSURLConnection sendAsynchronousRequest: request queue: queue completionHandler: ^(NSURLResponse* response, NSData* data, NSError* error)
{
NSLog(#"%#",[data bytes]);
}];
So I just need the data contained in the URL.But after few seconds (probably in the time that the newly created thread loads the data) the application crashes:
thread 6 : EXC_BAD_ACCESS (code=13, address=0x0)
The exact point is objc_msgSend_vtable5, in the NSLog line, when I try to print data bytes.
PS: I'm using ARC.
The problem is that the method -[NSData bytes] has return type void * (and is a pointer to a raw byte buffer), but you're treating the return value as an object by trying to log it using the %# format specifier. To fix this, just print just print data rather than [data bytes]; replace your line
NSLog(#"%#", [data bytes]);
with
NSLog(#"%#", data);

Parsing JSON value in objective c error?

I use ASIHTTPRequest to get a token, and I receive this string:
{Token:[{"new":"jkajshdkjashdjhasjkdhjkhd+sd==sfbjhdskfbks+sdjfbs=="}]}
I used JSON Framework from here: http://stig.github.com/json-framework.
This is the code after I get the string:
- (void)requestFinished:(ASIHTTPRequest *)req
{
NSString *responseString = [req responseString];
NSLog(#"Response: %#", [req responseString]);
// Parse the response
SBJsonParser *jsParser = [SBJsonParser new];
id content = [responseString JSONValue];
if(!content){
// Parsing error
NSLog(#"%#", jsParser.errorTrace);
}
}
NSLog(#"ID: %#", content);
I receive this error:
-JSONValue failed. Error trace is: (
"Error Domain=org.brautaset.JSON.ErrorDomain Code=3 \"Object key string expected\" UserInfo=0x5a418a0 {NSLocalizedDescription=Object key string expected}"
)
My guess is that, the JSON Framework that I am using cant understand the response string format:
{Token:[{"new":"jkajshdkjashdjhasjkdhjkhd+sd==sfbjhdskfbks+sdjfbs=="}]}
Is there any other way to parse the value?
Happy programming,
Johnie
It was looking for a start and end " surrounding Token.
{"Token":[{"new":"jkajshdkjashdjhasjkdhjkhd+sd==sfbjhdskfbks+sdjfbs=="}]}
There's a bug in this code:
SBJsonParser *jsParser = [SBJsonParser new];
id content = [responseString JSONValue];
if(!content){
// Parsing error
NSLog(#"%#", jsParser.errorTrace);
}
You instantiate a parser, jsParser, but don't use it to parse the string. (The JSONValue method instantiates a new parser internally.) Then you read the error from the parser that was not used to parse the string.