How to make a POST request with an array in body data - objective-c

I'm trying to do this with Objective-C but i think is the same body data but a don't know how it has to be.

I found the way to do this:
POST request
head: </*Your route*/>
body:
p=aString&p=bString&p=cString&p=dString
And then in the server you get:
body : {
p : [{
"aString",
"bString",
"cString",
"dString"
}]
}
Thanks for the support :)

One way (not sure the best way) is to encode the array in the POST data by sending the # of elements as a POST data field. For example
NSArray *array = #[#"hi", #"there"];
NSMutableString *postData = [NSMutableString stringWithFormat:#"array_length=%d", array.count];
for (int i=0; i<array.count; ++i)
[postData appendFormat:#"&array_%d=%#", i, array[i]];
// ...
The decoder, then, takes array_length and iterates over i = [0 .. array_length-1] to repopulate the array with array_0, array_1, ....

Here are two methods I used in an old project. You'll need to set the NSURLConnectionDelegate and implement the required methods.
// Check if the URLString is a valid data object
- (void) formatURLString: (NSString *) target forData:(NSArray *) data
{
if ([NSJSONSerialization isValidJSONObject:data])
{
NSError *error;
NSData *JSONdata = [NSJSONSerialization dataWithJSONObject:data options:kNilOptions error:&error];
// *** POST ***//
[self post:target withJSON:JSONdata];
} else
{
NSLog(#"Invalid JSON object. JSON object: %#", data);
}
}
- (void) post: (NSString *) target withJSON: (NSData *) jsonData
{
// Inform user network activity is taking place
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
NSMutableURLRequest *urlRequest =
[[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:target]];
[urlRequest setHTTPMethod:#"POST"];
[urlRequest addValue:#"postValues" forHTTPHeaderField:#"METHOD"];
[urlRequest setHTTPBody:jsonData];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:urlRequest
delegate:self];
if (!connection) { NSLog(#"Connection Failed"); }
}

Related

Error 400 and 415 when exchanging code for access_token

I am writing an application to authorise itself into Spotify. I used the node app.js example to get things working and an now re-writing natively into Objective C. I have extracted the authorisation code via a callback function
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:#"https://accounts.spotify.com/api/token"]];
request.HTTPMethod = #"POST";
// put in the header fields
NSString *headerString = [NSString stringWithFormat:#"%#:%#",clientID,clientSecret];
NSData *nsdata = [headerString dataUsingEncoding:NSUTF8StringEncoding];
NSString *base64Encoded = [nsdata base64EncodedStringWithOptions:0];
base64Encoded = [ NSString stringWithFormat:#"Basic %#", base64Encoded];
[request setValue:base64Encoded forHTTPHeaderField:#"Authorization"];
NSLog(#"request.header %#", request.allHTTPHeaderFields.description);
// put in the body form
NSString * stringData = [NSString stringWithFormat:#"grant_type:%#, code:%#, redirect_uri:\"%#\"", #"authorization_code",authorisationCode,redirectUri];
NSData * requestBodyData = [stringData dataUsingEncoding:NSUTF8StringEncoding];
request.HTTPBody = requestBodyData;
NSLog(#"request.body %#", [[NSString alloc] initWithData:request.HTTPBody encoding:NSUTF8StringEncoding]);
I then post this request and get
{"error":"server_error","error_description":"Unexpected status: 415"}
returned.
I have found a variety of questions on this topic revolving around the Content-Type needing to be application/x-www-form-urlencoded but this was no direct cure.
Anyone got any suggestions for me?
I found the answer here NSURLRequest : Post data and read the posted page
It appears that the raw data within the HTTPBody needs to be formatted differently - no JSON at all. The above link has a useful function which I updated slightly
-(NSData*)encodeDictionary:(NSDictionary*)dictionary {
NSMutableArray *parts = [[NSMutableArray alloc] init];
for (NSString *key in dictionary) {
NSString *encodedValue = [[dictionary objectForKey:key] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPasswordAllowedCharacterSet]];
NSString *encodedKey = [key stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLPasswordAllowedCharacterSet]];
NSString *part = [NSString stringWithFormat: #"%#=%#", encodedKey, encodedValue];
[parts addObject:part];
}
NSString *encodedDictionary = [parts componentsJoinedByString:#"&"];
return [encodedDictionary dataUsingEncoding:NSUTF8StringEncoding];
}
and ..
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
//NSLog(#"request.header %#", request.allHTTPHeaderFields.description);
// put in the body form using the new function
NSDictionary * parameters = [[NSDictionary alloc] initWithObjectsAndKeys:#"authorization_code",#"grant_type",authorisationCode,#"code",redirectUri,#"redirect_uri", nil ];
NSData * requestBodyData = [self encodeDictionary:parameters];
request.HTTPBody = requestBodyData;

Objective-C how to convert nsdata from web service to nsarray

How do i convert id to an array?
I have an apple app that talks to a server.
Issue i have is the app returns the data in the form of id however i need to convert this to an array as the actual returned data looks like the following.
[["30","2",1],["15","67",1],["30","4",1]]
It is actually the output from a mysql server
The actual app code looks like the following
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:#"blah blah"]];
NSURL_Layer * connection = [[NSURL_Layer alloc]initWithRequest:request];
[connection setCompletitionBlock:^(id obj, NSError *err) {
if (!err) {
//Need to convert the id to nsarray here, dunno how
} else {
//There was an error
}
}];
[connection start];
The NSURL.h
-(id)initWithRequest:(NSURLRequest *)req;
#property (nonatomic,copy)NSURLConnection * internalConnection;
#property (nonatomic,copy)NSURLRequest *request;
#property (nonatomic,copy)void (^completitionBlock) (id obj, NSError * err);
-(void)start;
NSURL.m
-(id)initWithRequest:(NSURLRequest *)req {
self = [super init];
if (self) {
[self setRequest:req];
}
return self;
}
-(void)start {
container = [[NSMutableData alloc]init];
internalConnection = [[NSURLConnection alloc]initWithRequest:[self request] delegate:self startImmediately:YES];
if(!sharedConnectionList)
sharedConnectionList = [[NSMutableArray alloc] init];
[sharedConnectionList addObject:self];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[container appendData:data];
}
//If finish, return the data and the error nil
-(void)connectionDidFinishLoading:(NSURLConnection *)connection {
if([self completitionBlock])
[self completitionBlock](container,nil);
[sharedConnectionList removeObject:self];
}
//If fail, return nil and an error
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
if([self completitionBlock])
[self completitionBlock](nil,error);
[sharedConnectionList removeObject:self];
}
Update:
i have added
NSURL_Layer * connection = [[NSURL_Layer alloc]initWithRequest:request];
[connection setCompletitionBlock:^(id obj, NSError *err) {
if (!err) {
NSError* error;
NSArray* array = [NSJSONSerialization JSONObjectWithData:obj options:NSJSONReadingAllowFragments error:&error];
} else {
//There was an error
}
}];
[connection start];
but returns error
error NSError * domain: #"NSCocoaErrorDomain" - code: 3840
_userInfo NSDictionary * 1 key/value pair
[0] (null) #"NSDebugDescription" : #"Invalid value around character 0."
Update: I put
NSLog(#"Data as string:%#", [[NSString alloc]initWithData:obj encoding:NSUTF8StringEncoding]);
which gave me a strange feedback. As a result i looked at my url request full code is below.
NSString *post = [NSString stringWithFormat:#"unique_id=%#&unique_password=%#",ServerUniqueID,ServerPassword];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%lu", (unsigned long)[post length]];
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:#"blah blah"]];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setHTTPBody:postData];
NSURL_Layer * connection = [[NSURL_Layer alloc]initWithRequest:request];
[connection setCompletitionBlock:^(id obj, NSError *err) {
if (!err)
{
NSError* error;
NSArray* array = [NSJSONSerialization JSONObjectWithData:[NSData dataWithData: obj] options:NSJSONReadingAllowFragments error:&error];
NSLog(#"Data as string:%#", [[NSString alloc]initWithData:obj encoding:NSUTF8StringEncoding]);
int temp = array.count;
}
else
{
//There was an error
}
}];
[connection start];
if i remove
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setHTTPBody:postData];
it works
if its in it dosn't so i have a whole new issue to look into.
you save the bytes into a container variable, alas the id infact NSData
(note id is just a 'wildcard pointer' that means ANY objC object)
so your id is NSData and from what you show it seems to be 3 json arrays... but no real JSON... (["30","2",1]["15","67",1]["30","4",1] isn't anything)
EITHER make the server send you JSON and THAT you can parse into a dictionary/array using NSJSONSerialization
OR write a custom separator to convert the data

Converting JSON Result as an Array

I have this JSON data :
array: {
data = (
{
"com_id" = 1;
"com_name" = Apple;
},
{
"com_id" = 2;
"com_name" = "Google";
},
{
"com_id" = 3;
"com_name" = "Yahoo";
}
);
message = "Data found";
response = success;
}
here's my code to fetch that data :
NSURL * url = [[NSURL alloc] initWithString:#"https://jsonurlhere.com"];
// Prepare the request object
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestReturnCacheDataElseLoad
timeoutInterval:30];
// Prepare the variables for the JSON response
NSData *urlData;
NSURLResponse *response;
NSError *error;
// Make synchronous request
urlData = [NSURLConnection sendSynchronousRequest:urlRequest
returningResponse:&response
error:&error];
// Construct a Array around the Data from the response
NSArray* object = [NSJSONSerialization
JSONObjectWithData:urlData
options:0
error:&error];
NSLog(#"array: %#", object);
now, I want to use that JSON data into my PickerView. how to change that JSON data into array so that I can load it to replace my existing array (self.nameCompany)?
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.nameCompany = #[#"Apple", #"Google", #"Yahoo"];
}
I think It's helpful to you. Can you try this following link? It's not use to any supporting files. Also, see this link NSJSONSerialization supported URL
NSJSONSerialization
check this code , your response is not a array but Dictionary.
-(void)loadData{
NSURL * url = [[NSURL alloc] initWithString:#"https://jsonurlhere.com"];
// Prepare the request object
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url
cachePolicy:NSURLRequestReturnCacheDataElseLoad
timeoutInterval:30];
// Prepare the variables for the JSON response
NSData *urlData;
NSURLResponse *response;
NSError *error;
// Make synchronous request
urlData = [NSURLConnection sendSynchronousRequest:urlRequest
returningResponse:&response
error:&error];
// Construct a Array around the Data from the response
NSDictionary* object = [NSJSONSerialization
JSONObjectWithData:urlData
options:0
error:&error];
NSLog(#"array: %#", [object objectForKey:#"data"]);
NSMutableArray *companyArray=[[NSMutableArray alloc] init];
for (NSDictionary *tempDict in [object objectForKey:#"data"]) {
[companyArray addObject:[tempDict objectForKey:#"com_name"]];
}
self.nameCompany=[NSArray arrayWithArray:companyArray];
}

iOS Read Json from web and display to tableView

What I am trying to do is read a json file on the web (I know the connection to this aspect is working) and then get some file contents to display on my tableView.
I was able to do this fine in another example but I'm not sure what the problem is now.
JSON File:
{
"entry":
[
{"Current Date":"Tuesday June 22 2011","Time Period":"00:00 - 06:45,"},
{"Current Date":"Tuesday June 23 2011","Time Period":"00:00 - 07:22"}
]
}
Button that fetches the JSON file from the web:
- (IBAction)getJsonButton:(id)sender {
[array removeAllObjects];
NSURL *url = [NSURL URLWithString:#"https://LinkToWhereJSONfileIsLocated/"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
connection = [NSURLConnection connectionWithRequest:request delegate:self];
if(connection)
{
webData = [[NSMutableData alloc]init];
}
}
Here's where I think I'm having my problem (must be my logic or syntax):
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSDictionary *allDataDictionary = [NSJSONSerialization JSONObjectWithData:webData options:0 error:nil];
NSArray *arrayOfEntry = [allDataDictionary objectForKey:#"entry"];
for (NSDictionary *diction in arrayOfEntry) {
NSString *currDate = [diction objectForKey:#"Current Date"];
[array addObject:currDate];
}
[[self myTableView]reloadData];
}
This is a quick guess, try calling reloadData method on main thread.

Get web service response data

I have made this so far. It's code that will make a json String request with an http Header. When i run this code i get no errors. But i get a Expression result unused warning. I should get a response from the web service after sending this http header.
code:
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *nid = #"";
NSString *vocab = #"";
NSString *inturl = #"testoverview";
NSString *mail = #"chh#fbr.dk";
NSString *md5pw = #"4d57e7ef1b7c3f431aca424764e9d786";
NSDictionary *jsonDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
nid, #"nid",
vocab, #"vocab",
inturl, #"inturl",
mail, #"mail",
md5pw, #"md5pw",nil];
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonDictionary options:NSJSONWritingPrettyPrinted error:&error];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
if (!jsonData) {
NSLog(#"Got an error; %#", error);
} else if(jsonData) {
NSString *url = #"http://www.taenk.dk/services/mobile";
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url] cachePolicy:NSURLCacheStorageAllowed timeoutInterval:30.0];
[request setValue:jsonString forHTTPHeaderField:#"X-FBR-App"];
[[NSURLConnection alloc] initWithRequest:request delegate:self]; <-- this line triggers the warning: "Expression result unused"
NSLog(#"jsonString %#", jsonString);
}
Can anybody clarify 2 things for me:
Does this trigger a response as soon as the request to the web service?
If yes, how do i print this result out?
You need to assign the result to a variable like
NSURLConnection *con = [[NSURLConnection alloc] initWithRequest:...
for later use (e.g. [con cancel];)
Then you should at least implement the delegate method connection:didFailWithError:. In the class reference I don't see the connection:didFinishLoading... anymore. Can you use the sendSynchronousRequest:returningResponse:error: instead, then you'll have the result, be it positive or negative.
This is how I retrieved the data (this version is without ARC):
- (void) connection :(NSURLConnection *)conn didReceiveData :(NSData *)data {
NSString *msg = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
[self checkAutoMailReply:msg];
[msg release];
}
msg contains the pure response data, no header or such.