views:

118

answers:

1

Hey, I need to make a HTTP POST request with an array of NSDictionary objects.

When I do this, however, I notice on the server side that the NSDictionary object does not get deserialized to a hash. It gets deserialized to a string - which is not what i want.

This is how I send the parameter from the client (IPhone) side:

ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
for (ABContact *c in contactsWithEmailsOrPhones){
  NSString *phoneNumber = [[ABContactsHelper class] contactPhoneNumber:c];
  NSString *email = [[c emailArray] objectAtIndex:0];
  NSLog(@"looping: %@, %@", phoneNumber, email);
  NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
                         phoneNumber,
                         @"phone", 
                         email,
                         @"email", 
                         [c firstname],
                         @"firstname",
                          [c lastname],
                          @"lastname", nil];

    [request addPostValue:dict forKey:@"contacts[]"];
}

[request setDelegate:self];
[request startAsynchronous];

This is how it looks when it is deserialized on the server (rails) side:

Started POST "/app/find_friends" for 67.164.97.48 at Thu Sep 23 14:40:37 -0700 2010
Processing by app#find_friends as HTML
Parameters: {"contacts"=>["{\n    email = \"xx\";\n    firstname = xx;\n    lastname = xx;\n    phone = \"xx\";\n}", "{\n    email = \"xx\";\n    firstname = xx;\n    lastname = xx;\n    phone = \"xx\";\n}"]}
Completed 200 OK in 0ms (Views: 0.3ms | ActiveRecord: 0.0ms)

I am sure this is a common problem that people face. So there definitely is a solution for this.

Thanks in advance for all the comments/answers.

A: 

Firstly, to explain what you're seeing:

The addPostValue method is designed to take a single value, and calls [value description] to convert that value into a string. The description method gives a string representation, which is what you're seeing on the server side (the description method is also what NSLog calls if you pass an object to it, so the format should look quite familiar). So the iphone has being asked to send a string, and does so, and the server is "correctly" showing that as a string.

If you just want to send a single contact, then just call 'addPostValue' for each key/value pair - ie. once for phone, again for email, etc.

If you want to pass multiple contacts you probably need something better. I'm not really familiar with ruby-on-rails so there may be other solutions, but certainly a common way to pass more complex data structures to webservices from the iphone is to use json.

There's a json library for the iphone here:

http://code.google.com/p/json-framework/

and ruby on rails has built in json support.

JosephH
Thanks for the response. I understand JSON is an option, but is that the only way hashes (maps) are sent as post parameters?
amehta
You could use SOAP or plain XML instead, but I'd consider JSON the simpler option. At the end of the day, a http POST is just sending (almost) freeform text to the server. If it is just a simple single dictionary then as I mentioned you can call addPostValue for each key/value (or modify ASIHTTPRequest so it will accept a dictionary and add each key/value), but for anything more complex you need something that structures the data into a string with a defined format that both the client and the server support - json is the simplest common way to do that.
JosephH
Ok. I was hoping that there was a non JSON/XML/SOAP/YAML way. I mean, when I call addPostValue - I am adding a key value pair. So, intuitively, I figured a *value* could be another Hash. Additionally, when I call addPostValue - it seems like it is allowing me to send an array as a parameter (as seen in the server log that I posted), so to me it seemed like a Hash object should also be supported. I guess not.
amehta