How to send json data in the Http request using NSURLRequest
Solution 1
Here's what I do (please note that the JSON going to my server needs to be a dictionary with one value (another dictionary) for key = question..i.e. {:question => { dictionary } } ):
NSArray *objects = [NSArray arrayWithObjects:[[NSUserDefaults standardUserDefaults]valueForKey:@"StoreNickName"],
[[UIDevice currentDevice] uniqueIdentifier], [dict objectForKey:@"user_question"], nil];
NSArray *keys = [NSArray arrayWithObjects:@"nick_name", @"UDID", @"user_question", nil];
NSDictionary *questionDict = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
NSDictionary *jsonDict = [NSDictionary dictionaryWithObject:questionDict forKey:@"question"];
NSString *jsonRequest = [jsonDict JSONRepresentation];
NSLog(@"jsonRequest is %@", jsonRequest);
NSURL *url = [NSURL URLWithString:@"https://xxxxxxx.com/questions"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
NSData *requestData = [jsonRequest dataUsingEncoding:NSUTF8StringEncoding];
[request setHTTPMethod:@"POST"];
[request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setValue:[NSString stringWithFormat:@"%d", [requestData length]] forHTTPHeaderField:@"Content-Length"];
[request setHTTPBody: requestData];
NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:self];
if (connection) {
receivedData = [[NSMutableData data] retain];
}
The receivedData is then handled by:
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSDictionary *jsonDict = [jsonString JSONValue];
NSDictionary *question = [jsonDict objectForKey:@"question"];
This isn't 100% clear and will take some re-reading, but everything should be here to get you started. And from what I can tell, this is asynchronous. My UI is not locked up while these calls are made. Hope that helps.
Solution 2
I struggled with this for a while. Running PHP on the server. This code will post a json and get the json reply from the server
NSURL *url = [NSURL URLWithString:@"http://example.co/index.php"];
NSMutableURLRequest *rq = [NSMutableURLRequest requestWithURL:url];
[rq setHTTPMethod:@"POST"];
NSString *post = [NSString stringWithFormat:@"command1=c1&command2=c2"];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding];
[rq setHTTPBody:postData];
[rq setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:rq queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
if ([data length] > 0 && error == nil){
NSError *parseError = nil;
NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
NSLog(@"Server Response (we want to see a 200 return code) %@",response);
NSLog(@"dictionary %@",dictionary);
}
else if ([data length] == 0 && error == nil){
NSLog(@"no data returned");
//no data, but tried
}
else if (error != nil)
{
NSLog(@"there was a download error");
//couldn't download
}
}];
Solution 3
I would suggest to use ASIHTTPRequest
ASIHTTPRequest is an easy to use wrapper around the CFNetwork API that makes some of the more tedious aspects of communicating with web servers easier. It is written in Objective-C and works in both Mac OS X and iPhone applications.
It is suitable performing basic HTTP requests and interacting with REST-based services (GET / POST / PUT / DELETE). The included ASIFormDataRequest subclass makes it easy to submit POST data and files using multipart/form-data.
Please note, that the original author discontinued with this project. See the followring post for reasons and alternatives: http://allseeing-i.com/%5Brequest_release%5D;
Personally I am a big fan of AFNetworking
Solution 4
Most of you already know this by now, but I am posting this, just incase, some of you are still struggling with JSON in iOS6+.
In iOS6 and later, we have the NSJSONSerialization Class that is fast and has no dependency on including "outside" libraries.
NSDictionary *result = [NSJSONSerialization JSONObjectWithData:[resultStr dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil];
This is the way iOS6 and later can now parse JSON efficiently.The use of SBJson is also pre-ARC implementation and brings with it those issues too if you are working in an ARC environment.
I hope this helps!
Solution 5
Here is a great article using Restkit
It explains on serializing nested data into JSON and attaching the data to a HTTP POST request.
Related videos on Youtube
Comments
-
Toran Billups almost 2 years
I'm new to objective-c and I'm starting to put a great deal of effort into request/response as of recent. I have a working example that can call a url (via http GET) and parse the json returned.
The working example of this is below
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { [responseData setLength:0]; } - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { [responseData appendData:data]; } - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { NSLog([NSString stringWithFormat:@"Connection failed: %@", [error description]]); } - (void)connectionDidFinishLoading:(NSURLConnection *)connection { [connection release]; //do something with the json that comes back ... (the fun part) } - (void)viewDidLoad { [self searchForStuff:@"iPhone"]; } -(void)searchForStuff:(NSString *)text { responseData = [[NSMutableData data] retain]; NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.whatever.com/json"]]; [[NSURLConnection alloc] initWithRequest:request delegate:self]; }
My first question is - will this approach scale up? Or is this not async (meaning I block the UI thread while the app is waiting for the response)
My second question is - how might I modify the request part of this to do a POST instead of GET? Is it simply to modify the HttpMethod like so?
[request setHTTPMethod:@"POST"];
And finally - how do I add a set of json data to this post as a simple string (for example)
{ "magic":{ "real":true }, "options":{ "happy":true, "joy":true, "joy2":true }, "key":"123" }
Thank you in advance
-
Josh over 13 yearsHere is a tutorial: mobileorchard.com/tutorial-json-over-http-on-the-iphone
-
-
Toran Billups over 13 yearsEverything looks good except the this line [dict objectForKey:@"user_question"], nil]; -- dict is not declared in your sample. Is this just a simple dictionary or something special?
-
Mike G over 13 yearsSorry about that. Yes, "dict" is just a simple dictionary that I load from the iOS users documents.
-
Rob over 11 yearsThis is using
NSDictionary
instance methodJSONRepresentation
. I might suggest I usingNSJSONSerialization
class methoddataWithJSONObject
, instead of the json-framework. -
respectTheCode almost 11 yearsIt is more efficient to convert the NSUInteger to an NSString through an NSNumber like
[[NSNumber numberWithUnsignedInt:requestData.length] stringValue]
. -
CouchDeveloper over 10 years@MikeG Fixed a long standing and so far unnoticed bug in the code sample. Sorry, for editing your post ;)
-
ahmad about 10 yearsthe question was about POST
-
auco about 10 yearsno, the first part of the question is about asynchronicity and there is no answer here that answers that. Cheers for the downvote.
-
Satyam about 10 yearsCan we achieve the same using GET instead of POST?
-
SamChen about 9 yearscontent type = "application/x-www-form-urlencoded" did the trick. Thanks
-
Steve Moser over 8 yearsMikeG Removed external dependency referred to by @Rob.
-
Steve Moser over 8 years@Rob well my edit was rejected 3 to 2 so I made my edit an answer here:stackoverflow.com/a/33505940/142358
-
Deepak Badiger about 8 yearsi was spending too much time investigating the reason for my nil response. This post helped me, especially setting the "content-type" and "content-length" along with "accept" to "application/json". This post has resolved my issue of nil data being returned from the web api. Thanks for the post.
-
Gajendra K Chauhan almost 7 yearsNice answer. I used "application/json" in my case
-
arniotaki almost 5 yearsCritical warning: 'initWithRequest:delegate:' is deprecated: first deprecated in iOS 9.0 - Use NSURLSession (see NSURLSession.h)