json PUT request - iphone

Hi iam usng JSONKit. i need to update status in linkedin site by sending the status update through json request to server. this is the code im sendin. im gettin 400 eroor. please tel me whats the mistake.
thanks.
NSMutableDictionary *jsonDict = [[NSMutableDictionary alloc] initWithObjectsAndKeys:#"linkedin-html",#"contentType",#"My Fancy Update",#"body",nil];
NSString *str =[jsonDict JSONString];
NSMutableData *requestData = [NSMutableData dataWithBytes:[str UTF8String] length:[str length]];
[self setHTTPBody:requestData];
[self setValue:[NSString stringWithFormat:#"%d", [requestData length]] forHTTPHeaderField:#"Content-Length"];
[self setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];

dont know if this will fit your usage needs exactly, I am using iphone and connecting to jayrock .net webservices.
Here is the command I use to handle all my calls.
Also, I am using the json-framework
- (NSDictionary*) sendJSONRPCRequestTo:(NSString*) url
forCommand:(NSString*)command
withParamaters:(NSMutableArray*) parameters
synchronous:(BOOL) sendSynchronous
{
if (parameters != nil)
{
[parameters setValue:[HSAppData appVersion] forKey:#"AppVersion"];
[parameters setValue:[NSNumber numberWithDouble:[HSAppData currentLocation].longitude] forKey:#"Longitude"];
[parameters setValue:[NSNumber numberWithDouble:[HSAppData currentLocation].latitude] forKey:#"Latitude"];
}
if (self.commandId == nil)
{
self.commandId = #"1";
}
NSMutableURLRequest *request = [self.baseTransaction makeNewRequestFor:url];
NSMutableDictionary *mainPackage = [NSMutableDictionary dictionary];
[mainPackage setValue:self.commandId forKey:#"id"];
[mainPackage setValue:command forKey:#"method"];
[mainPackage setValue:parameters forKey:#"params"];
NSString *jsonData = [mainPackage JSONRepresentation];
[request setValue:command forHTTPHeaderField:#"X-JSON-RPC"];
[request setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
if (jsonData != nil && [jsonData isEqual:#""] == NO)
{
[request setHTTPMethod:#"POST"];
[request setValue:[[NSNumber numberWithInt:[jsonData length]] stringValue] forHTTPHeaderField:#"Content-Length"];
}
[request setHTTPBody:[jsonData dataUsingEncoding:NSUTF8StringEncoding]];
if (sendSynchronous)
{
NSHTTPURLResponse * response = nil;
NSError * error = nil;
//self.baseTransaction.lastConnection = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString *jsonResult = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
NSDictionary *jsonDict = nil;
#try {
jsonDict = [jsonResult JSONValue];
}
#catch (NSException * e) {
NSLog(#"Error: %#",jsonResult);
jsonDict = [NSMutableDictionary dictionary];
[jsonDict setValue:self.commandId forKey:#"id"];
[jsonDict setValue:#"Unable to call function on server" forKey:#"error"];
[jsonDict setValue:[NSNull null] forKey:#"result"];
}
#finally {
return jsonDict;
}
}
// TODO: Add ASynchronous
// else
// {
// }
}

I would start by writing your json payload and the connection response data to a simple text file and review (or post, if you want us to take a look). I've found that's the easiest way for me to spot issues when posting data to services. You're using a library, so my guess is the payload should be fine, but you never know. The response data may include more hints to the true issue, although I can't say I've ever used LinkedIn's api.
Also, I didn't see where you specified that the request was a "PUT". Did you include
[req setHTTPMethod:#"PUT"];
Use this code to write the payload to the file system (sorry for the formatting, it's not playing nicely with mobile safari):
NSString *documentsDirectoryPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *documentPath = [NSString stringWithFormat:#"%#/payloadData.txt", documentsDirectoryPath];
[requestData writeToFile:documentPath atomically:YES];

May be this can help you.

Related

DocuSign error downloading document

I'm trying to implement this example link of a DocuSign service that download an envelope document, but when the execution arrive to this line in step 3:
NSMutableString *jsonResponse = [[NSMutableString alloc] initWithData:oResponseData encoding:NSUTF8StringEncoding];
jsonResponse is nil and when I open the document, it has a lot of strange characters and I can't read it.
My code for downloadind is the following:
NSString *url = #"https://demo.docusign.net/restapi/v2/accounts/373577/envelopes/08016140-e4dc-4697-8146-f8ce801abf92/documents/1";
NSMutableURLRequest *documentsRequest = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:url]];
[documentsRequest setHTTPMethod:#"GET"];
[documentsRequest setURL:[NSURL URLWithString:url]];
[documentsRequest setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[documentsRequest setValue:[self jsonStringFromObject:authenticationHeader] forHTTPHeaderField:#"X-DocuSign-Authentication"];
NSError *error1 = [[NSError alloc] init];
NSHTTPURLResponse *responseCode = nil;
NSData *oResponseData = [NSURLConnection sendSynchronousRequest:documentsRequest returningResponse:&responseCode error:&error1];
NSMutableString *jsonResponse = [[NSMutableString alloc] initWithData:oResponseData encoding:NSUTF8StringEncoding];
if([responseCode statusCode] != 200){
NSLog(#"Error sending %# request to %#\nHTTP status code = %i", [documentsRequest HTTPMethod], url, [responseCode statusCode]);
NSLog( #"Response = %#", jsonResponse );
return;
}
// download the document to the same directory as this app
NSString *appDirectory = [[[NSBundle mainBundle] bundlePath] stringByDeletingLastPathComponent];
NSMutableString *filePath = [NSMutableString stringWithFormat:#"%#/%#", appDirectory, #"eee"];
[oResponseData writeToFile:filePath atomically:YES];
NSLog(#"Envelope document - %# - has been downloaded to %#\n", #"eee", filePath);
If no data is coming back from
NSMutableString *jsonResponse = [[NSMutableString alloc] initWithData:oResponseData encoding:NSUTF8StringEncoding];
then that means oResponseData is most likely nil which means the URL is not being constructed correctly for each envelope document. Are you doing step 2 in the sample that you linked to, where it first retrieves the envelopeDocuments information about the envelope, then it dynamically builds each unique document uri in preparation of downloading each one.
Instead of hardcoding your URL you should dynamically retrieve the envelopeDocuments data, then build each document uri dynamically then your response data will not be nil. Here's the full working sample:
- (void)getDocumentInfoAndDownloadDocuments
{
// Enter your info:
NSString *email = #"<#email#>";
NSString *password = #"<#password#>";
NSString *integratorKey = #"<#integratorKey#>";
// need to copy a valid envelopeId from your account
NSString *envelopeId = #"<#envelopeId#>";
///////////////////////////////////////////////////////////////////////////////////////
// STEP 1 - Login (retrieves accountId and baseUrl)
///////////////////////////////////////////////////////////////////////////////////////
NSString *loginURL = #"https://demo.docusign.net/restapi/v2/login_information";
NSMutableURLRequest *loginRequest = [[NSMutableURLRequest alloc] init];
[loginRequest setHTTPMethod:#"GET"];
[loginRequest setURL:[NSURL URLWithString:loginURL]];
// set JSON formatted X-DocuSign-Authentication header (XML also accepted)
NSDictionary *authenticationHeader = #{#"Username": email, #"Password" : password, #"IntegratorKey" : integratorKey};
// jsonStringFromObject() function defined further below...
[loginRequest setValue:[self jsonStringFromObject:authenticationHeader] forHTTPHeaderField:#"X-DocuSign-Authentication"];
// also set the Content-Type header (other accepted type is application/xml)
[loginRequest setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[NSURLConnection sendAsynchronousRequest:loginRequest queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *loginResponse, NSData *loginData, NSError *loginError) {
if (loginError) { // succesful GET returns status 200
NSLog(#"Error sending request %#. Got Response %# Error is: %#", loginRequest, loginResponse, loginError);
return;
}
// we use NSJSONSerialization to parse the JSON formatted response
NSError *jsonError = nil;
NSDictionary *responseDictionary = [NSJSONSerialization JSONObjectWithData:loginData options:kNilOptions error:&jsonError];
NSArray *loginArray = responseDictionary[#"loginAccounts"];
// parse the accountId and baseUrl from the response (other data included)
NSString *accountId = loginArray[0][#"accountId"];
NSString *baseUrl = loginArray[0][#"baseUrl"];
//--- display results
NSLog(#"\naccountId = %#\nbaseUrl = %#\n", accountId, baseUrl);
///////////////////////////////////////////////////////////////////////////////////////
// STEP 2 - Get Document Info for specified envelope
///////////////////////////////////////////////////////////////////////////////////////
// append /envelopes/{envelopeId}/documents URI to baseUrl and use as endpoint for next request
NSString *documentsURL = [NSMutableString stringWithFormat:#"%#/envelopes/%#/documents", baseUrl, envelopeId];
NSMutableURLRequest *documentsRequest = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:documentsURL]];
[documentsRequest setHTTPMethod:#"GET"];
[documentsRequest setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[documentsRequest setValue:[self jsonStringFromObject:authenticationHeader] forHTTPHeaderField:#"X-DocuSign-Authentication"];
[NSURLConnection sendAsynchronousRequest:documentsRequest queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *documentsResponse, NSData *documentsData, NSError *documentsError) {
NSError *documentsJSONError = nil;
NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:documentsData options:kNilOptions error:&documentsJSONError];
if (documentsError){
NSLog(#"Error sending request: %#. Got response: %#", documentsRequest, documentsResponse);
NSLog( #"Response = %#", documentsResponse );
return;
}
NSLog( #"Documents info for envelope is:\n%#", jsonResponse);
NSError *jsonError = nil;
NSDictionary *responseDictionary = [NSJSONSerialization JSONObjectWithData:documentsData options:kNilOptions error:&jsonError];
// grab documents info for the next step...
NSArray *documentsArray = responseDictionary[#"envelopeDocuments"];
///////////////////////////////////////////////////////////////////////////////////////
// STEP 3 - Download each envelope document
///////////////////////////////////////////////////////////////////////////////////////
NSMutableString *docUri;
NSMutableString *docName;
NSMutableString *docURL;
// loop through each document uri and download each doc (including the envelope's certificate)
for (int i = 0; i < [documentsArray count]; i++)
{
docUri = [documentsArray[i] objectForKey:#"uri"];
docName = [documentsArray[i] objectForKey:#"name"];
docURL = [NSMutableString stringWithFormat: #"%#/%#", baseUrl, docUri];
[documentsRequest setHTTPMethod:#"GET"];
[documentsRequest setURL:[NSURL URLWithString:docURL]];
[documentsRequest setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[documentsRequest setValue:[self jsonStringFromObject:authenticationHeader] forHTTPHeaderField:#"X-DocuSign-Authentication"];
NSError *error = [[NSError alloc] init];
NSHTTPURLResponse *responseCode = nil;
NSData *oResponseData = [NSURLConnection sendSynchronousRequest:documentsRequest returningResponse:&responseCode error:&error];
NSMutableString *jsonResponse = [[NSMutableString alloc] initWithData:oResponseData encoding:NSUTF8StringEncoding];
if([responseCode statusCode] != 200){
NSLog(#"Error sending %# request to %#\nHTTP status code = %i", [documentsRequest HTTPMethod], docURL, [responseCode statusCode]);
NSLog( #"Response = %#", jsonResponse );
return;
}
// download the document to the same directory as this app
NSString *appDirectory = [[[NSBundle mainBundle] bundlePath] stringByDeletingLastPathComponent];
NSMutableString *filePath = [NSMutableString stringWithFormat:#"%#/%#", appDirectory, docName];
[oResponseData writeToFile:filePath atomically:YES];
NSLog(#"Envelope document - %# - has been downloaded to %#\n", docName, filePath);
} // end for
}];
}];
}
- (NSString *)jsonStringFromObject:(id)object {
NSString *string = [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:object options:0 error:nil] encoding:NSUTF8StringEncoding];
return string;
}

How to post json data to server [duplicate]

This question already has an answer here:
How to send json post values to a remote server and get the results with iOS 5?
(1 answer)
Closed 9 years ago.
In my iPhone app I want to send my data in JSON format.I have stored all the data in an dictionary.How to change dictionary data in JSON format and then send it to the serve using post method (I need to send to server only).
If your using SBJSON then using the code below you can create JSON string from NSDictionary.
SBJsonWriter *jsonWriter = [SBJsonWriter new];
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithObjects:values forKeys:keys];
NSString *jsonString = [jsonWriter stringWithObject:dict];
try it
NSMutableDictionary *Dict=[[NSMutableDictionary alloc] initWithObjectsAndKeys:str,#"str",str1,#"str1",Idstr,#"Idstr",nil];
NSError *error=nil;
NSData *Data=[NSJSONSerialization dataWithJSONObject:Dict options:NSJSONWritingPrettyPrinted error:&error];
NSMutableString *JsonString = [[NSMutableString alloc] initWithData:Data encoding:NSUTF8StringEncoding];
NSMutableString *urlstr=#"url"
NSURL *url=[NSURL URLWithString:urlstr];
NSMutableURLRequest *urlrequest=[NSMutableURLRequest requestWithURL:url];
NSString *urlbody=[NSString stringWithFormat:#"inputParam=%#",JsonString];
[urlrequest setHTTPBody:[Alerturlbody dataUsingEncoding:NSUTF8StringEncoding]];
[urlrequest setHTTPMethod:#"POST"];
[urlrequest setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Accept"];
[urlrequest setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[urlrequest setValue:[NSString stringWithFormat:#"%d", [urlbody length]] forHTTPHeaderField:#"Content-Length"];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:urlrequest queue:queue completionHandler:^(NSURLResponse *response, NSData *Resdata, NSError *error)
{
NSError* error;
NSDictionary *jsondict = [NSJSONSerialization
JSONObjectWithData:Resdata //1
options:kNilOptions
error:&error];
//NSLog(#"jsondict:%#",jsondict);
}
else if ([Resdata length] == 0 && error == nil)
{
NSLog(#"Nothing was downloaded.");
else if (error != nil)
{
NSLog(#"Error happened = %#", error);
}
}];

Create a JsonString in iOS

I am new in iOS. I created a JSON NSDictionary like this:
NSArray *keys = [NSArray arrayWithObjects:#"User", #"Password", nil];
NSArray *objects = [NSArray arrayWithObjects:#"Ali", #"2020", nil];
NSDictionary *jsonDictionary = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
And then I could convert it to NSString via two mechanisms:
1)
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonDictionary options:0 error:&error];
NSString *jsonString = nil;
if (! jsonData) {
NSLog(#"Got an error: %#", error);
} else {
jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
}
2)
NSString *jsonString = [jsonDictionary JSONRepresentation];
In the second way I get this warning :
Instance method '-JSONRepresentation' not found (return type defaults to 'id')
But when I run the project, both of the mechanisms works fine:
NSLog(#"Val of json parse obj is %#",jsonString);
Do you know how can I remove the warning in the second way?
My main goal is POST this json String to an external database using RESTful Web Service.
Basically which way is better considering my main goal?
You should use NSJSONSerialization as it is faster and comes directly with iOS SDK as long as your "target audience" is iOS5+
To POST the data to your web service you need the create a request along these lines...
NSDictionary * postDictionary = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:#"value1", #"value2", nil]
forKeys:[NSArray arrayWithObjects:#"key1", #"key2", nil]];
NSError * error = nil;
NSData * jsonData = [NSJSONSerialization dataWithJSONObject:postDictionary options:NSJSONReadingMutableContainers error:&error];
NSMutableURLRequest * urlRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"your_webservice_post_url"]];
[urlRequest setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[urlRequest setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[urlRequest setHTTPMethod:#"POST"];
[urlRequest setHTTPBody:jsonData];
NSURLConnection * myConnection = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self startImmediately:YES];
Please read up on NSURLConnectionDelegate protocol.
For iOS 5.0 > :
Use NSJSONSerialization like this :
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionary options:NSJSONWritingPrettyPrinted error:&error];
NSString *resultAsString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSLog(#"jsonData as string:\n%# Error:%#", resultAsString,error);
For < iOS 5 :
Use json-framework a third party library that uses category for NSDictionary to provide json string :
NSString *jsonString = [dictionary JSONRepresentation];
//with options
NSString *jsonString = [dictionary JSONStringWithOptions:JKSerializeOptionNone error:nil]
This will help you... Convert NSDictionary to JSON with SBJson
use this way i hope it will help you
NSArray *keys = [NSArray arrayWithObjects:#"User", #"Password", nil];
NSArray *objects = [NSArray arrayWithObjects:#"Ali", #"2020", nil];
NSDictionary *jsonDictionary = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
NSError *error = nil;
// NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonDictionary options:0 error:&error];
id result = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&error];
NSLog(#"\n\n\n id for json==%# \n\n\n\n\n",result);
JSON DEFAULT METHOD......
+(NSDictionary *)stringWithUrl:(NSURL *)url postData:(NSData *)postData httpMethod:(NSString *)method {
NSDictionary *returnResponse=[[NSDictionary alloc]init];
#try {
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:180]; [urlRequest setHTTPMethod:method];
if(postData != nil)
{
[urlRequest setHTTPBody:postData];
}
[urlRequest setValue:#"application/json" forHTTPHeaderField:#"Content-Type"];
[urlRequest setValue:#"application/json" forHTTPHeaderField:#"Accept"];
[urlRequest setValue:#"text/html" forHTTPHeaderField:#"Accept"];
NSData *urlData;
NSURLResponse *response;
NSError *error;
urlData = [NSURLConnection sendSynchronousRequest:urlRequest
returningResponse:&response
error:&error];
returnResponse = [NSJSONSerialization
JSONObjectWithData:urlData
options:kNilOptions
error:&error];
} #catch (NSException *exception) { returnResponse=nil; } #finally { return returnResponse; } }
Return Method :
+(NSDictionary )methodName:(NSString)string {
NSDictionary *returnResponse; NSData *postData = [NSData dataWithBytes:[string UTF8String] length:[string length]]; NSString *urlString = #"https//:..url...."; returnResponse=[self stringWithUrl:[NSURL URLWithString:urlString] postData:postData httpMethod:#"POST"];
return returnResponse;
}

Sending form data via HTTP Post [Objective C]

I have a form data from an iphone app that needs to send HTTP Post variables to a URL.
The thing is, I've been told not to use setHTTPBody, but am unsure of how else to do it as every example I see uses setHTTPBody; even those that use POST methods.
To make things matters a little more complicated, the URL/webpage requires a submit=true and action=enquiry in the post variables.
Here's what I have so far.
NSString *formContactName = [self contactName];
NSString *formEmail = [self email];
NSString *formPhone = [self phone];
NSString *formComments = [self comments];
// The above data is fine, as explored here.
NSLog(#"formContactName = %#", formContactName);
NSLog(#"formEmail = %#", formEmail);
NSLog(#"formPhone = %#", formPhone);
NSLog(#"formComments = %#", formComments);
// Setup request
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
[request setURL:[NSURL URLWithString:advertURL]];
[request setHTTPMethod:#"POST"];
// set headers
NSString *contentType = [NSString stringWithFormat:#"text/plain"];
[request addValue:contentType forHTTPHeaderField:#"Content-Type"];
// setup post string
NSMutableString *postString = [[NSMutableString alloc] init];
[postString appendFormat:#"contactname=%#", formContactName];
[postString appendFormat:#"&email=%#", formEmail];
[postString appendFormat:#"&phone=%#", formPhone];
[postString appendFormat:#"&comments=%#", formComments];
[postString appendFormat:#"&submit=yes"];
[postString appendFormat:#"&action=enquiry"];
// I've been told not to use setHTTPBody for post variables, but how else do you do it?
[request setHTTPBody:[postString dataUsingEncoding:NSUTF8StringEncoding]];
// get response
NSHTTPURLResponse *urlResponse = nil;
NSError *error = [[NSError alloc] init];
NSData *responseData = [NSURLConnection sendSynchronousRequest:request
returningResponse:&urlResponse
error:&error];
NSString *result = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSLog(#"Response code: %d", [urlResponse statusCode]);
if ([urlResponse statusCode] >=200 && [urlResponse statusCode] <300)
{
NSLog(#"Response ==> %#", result);
}
[result release];
[error release];
I always get a 200 result, which is good. But the response back indicates that the Post variables are not getting through.
The response back has a field in it called "enquirysent" and its always blank. If the Post variables are successful, it should return a "1" or true statement.
"enquirysent": ""
Therefore, my question is: How do I force the HTTP-POST variables in the above request?
Thanks.
you can use ASIHTTPRequest to simplify:
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setPostValue:#"Ben" forKey:#"first_name"];
[request setPostValue:#"Copsey" forKey:#"last_name"];
[request setFile:#"/Users/ben/Desktop/ben.jpg" forKey:#"photo"];

How to send json data in the Http request using NSURLRequest

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
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.
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
}
}];
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
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!
Here is a great article using Restkit
It explains on serializing nested data into JSON and attaching the data to a HTTP POST request.
Since my edit to Mike G's answer to modernize the code was rejected 3 to 2 as
This edit was intended to address the author of the post and makes no
sense as an edit. It should have been written as a comment or an
answer
I'm reposting my edit as a separate answer here. This edit removes the JSONRepresentation dependency with NSJSONSerialization as Rob's comment with 15 upvotes suggests.
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"];
NSLog(#"jsonRequest is %#", jsonRequest);
NSURL *url = [NSURL URLWithString:#"https://xxxxxxx.com/questions"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
NSData *requestData = [NSJSONSerialization dataWithJSONObject:dict options:0 error:nil]; //TODO handle error
[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:
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSDictionary *question = [jsonDict objectForKey:#"question"];
Here's an updated example that is using NSURLConnection +sendAsynchronousRequest: (10.7+, iOS 5+), The "Post" request remains the same as with the accepted answer and is omitted here for the sake of clarity:
NSURL *apiURL = [NSURL URLWithString:
[NSString stringWithFormat:#"http://www.myserver.com/api/api.php?request=%#", #"someRequest"]];
NSURLRequest *request = [NSURLRequest requestWithURL:apiURL]; // this is using GET, for POST examples see the other answers here on this page
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if(data.length) {
NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
if(responseString && responseString.length) {
NSLog(#"%#", responseString);
}
}
}];
You can try this code for send json string
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:ARRAY_CONTAIN_JSON_STRING options:NSJSONWritin*emphasized text*gPrettyPrinted error:NULL];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSString *WS_test = [NSString stringWithFormat:#"www.test.com?xyz.php&param=%#",jsonString];