3

I've been struggling with this for the last few days; I am trying to post an array to PHP. I can successfully send it, but it's not taken in with a post-variable (I am trying to use the variable key "json"... With this code, I receive the array in php:

Objective-C

NSError *error;
NSDictionary *jsonDictionary = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects: @"one", @"two", @"three", nil] forKeys: [NSArray arrayWithObjects: @"a", @"b", @"c", nil]];
NSArray *jsonArray = [NSArray arrayWithObject:jsonDictionary];
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:jsonArray options:NSUTF8StringEncoding error:&error];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"somewebservicelocation/arrayTest.php?json="]];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setHTTPMethod:@"POST"];
[request setHTTPBody:jsonData];
NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSString *response = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding];
NSLog(@"response: %@",response);

PHP

$handle = fopen('php://input','r');
    $array = fgets($handle);
    echo $array;
    if(isset($array))
    {
        echo "success";
    }
    else
    {
        echo "failure";
    }

If I use this PHP, using _POST, I get no love:

$rawJsonData = $_POST['json'];
$array = json_decode(stripslashes($rawJsonData),true);
echo $array;
if(isset($array))
{
    echo "success";
}
else
{
    echo "failure";
}

...I've been at it for several days - all over Stack Overflow, and understand I need to include the variable and data in the body of the request, but I just can't get it to work. What am I doing wrong? How do you go about this differently? Save me from this headache...

3
  • I'm not sure why you need the _POST rendition, but I've provided an example of that in the latter part of my answer. Commented Jun 4, 2013 at 7:54
  • a) sometimes i will be sending other variables with the arrays (yes, i know i could manipulate the arrays to be bigger, but i don't think this is the best practice). b) because i'm sure it's possible... Commented Jun 4, 2013 at 7:56
  • As I said below, I definitely prefer the structuring the NSDictionary that I json-encode to capture all of these items I want to pass. The _POST structure feels like a web-browser-forms technology that doesn't lend itself this sort of computer-to-computer communication which JSON excels at (though it can be contorted to do so). Both techniques work, but I'd lean towards the consolidated JSON approach, not the mix of _POST and JSON approach. But use whichever works for you. Commented Jun 4, 2013 at 8:13

2 Answers 2

6

On the PHP side, I've used something similar to your first example:

<?php

$handle = fopen("php://input", "rb");
$http_raw_post_data = '';
while (!feof($handle)) {
    $http_raw_post_data .= fread($handle, 8192);
}
fclose($handle);

// do what you want with it
//
// For diagnostic purposes, I'm just going to decode, make sure I got an array, 
// and respond with JSON that includes status, code, and the original request

$post_data = json_decode($http_raw_post_data,true);

if (is_array($post_data))
    $response = array("status" => "ok", "code" => 0, "original request" => $post_data);
else
    $response = array("status" => "error", "code" => -1, "original_request" => $post_data);

$processed = json_encode($response);
echo $processed;

?>

And then on the iOS side, I use:

// create the dictionary (or array)

NSDictionary *dictionary = @{@"a": @"One", @"b": @"Two", @"c": @"Three"};
NSError *error = nil;
NSData *data = [NSJSONSerialization dataWithJSONObject:dictionary options:0 error:&error];
if (error)
    NSLog(@"%s: JSON encode error: %@", __FUNCTION__, error);

// create the request

NSURL *url = [NSURL URLWithString:@"your.url.here"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setValue:@"application/json; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:data];

// issue the request

NSURLResponse *response = nil;
NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
if (error)
    NSLog(@"%s: NSURLConnection error: %@", __FUNCTION__, error);

// examine the response

NSString *responseString = [[NSString alloc] initWithData:returnData encoding:NSUTF8StringEncoding];
NSLog(@"responseString: %@",responseString);

I just tested this round trip, and it works fine.


If you are determined to use the _POST technique, what works for me is to set the the data to be json=%@, such as:

NSDictionary *dictionary = ...
NSData *data = [NSJSONSerialization dataWithJSONObject:dictionary options:0 error:&error];
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
if (error)
    NSLog(@"%s: JSON encode error: %@", __FUNCTION__, error);

NSURL *url = [NSURL URLWithString:@"your.url.here"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

[request setHTTPMethod:@"POST"];
NSString *params = [NSString stringWithFormat:@"json=%@",
                    [string stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSData *paramsData = [params dataUsingEncoding:NSUTF8StringEncoding];
[request addValue:@"8bit" forHTTPHeaderField:@"Content-Transfer-Encoding"];
[request addValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[request setHTTPBody:paramsData];

// now send the request, like before

And the PHP to parse it is much like you had:

$http_raw_post_data = $_POST['json'];

$post_data = json_decode(stripslashes($http_raw_post_data),true);

if (is_array($post_data))
    $response = array("status" => "ok", "code" => 0, "original request" => $post_data);
else
    $response = array("status" => "error", "code" => -1, "original_request" => $post_data);

$processed = json_encode($response);
echo $processed;
Sign up to request clarification or add additional context in comments.

11 Comments

thanks, but what if i want to send multiple arrays and strings, etc. as well?
@Ryan I'd use the first technique (that avoids adding percent escapes on the way out and stripping slashes on the way in), but add the multiple arrays and strings to my NSMutableDictionary that I encode with JSON. You can nest dictionaries and arrays to your heart's content (look at my sample response, which is a dictionary with three keys, of which the third's value is another dictionary (in this example, just another copy of the one I uploaded)). Using a HTML POST is not the way to solve this. Structure your JSON to handle all of the different values, etc. that you want to send.
edit: ah brilliant. can't thank you enough! edit2: the reason i wanted to be able to add external variables is for security or distinguishing source (using keys before connecting/downloading data).
Hi Rob, I just took your iOS code and php code and replaced the dictionary for an array but it crashes right after the NSJSONSerialization line. No error log. Just bad EXC ACCESS :(
@marciokoko If it's crashing at dataWithJSONObject, check that the array you passed to it was non-nil. The above code was from a working sample, so I don't see any other way it would crash at the NSJSONSerialization like. Is the array just an array of dictionaries and or standard Cocoa objects? Or do you have your own objects in that array? NSLog the contents of the array before you call dataWithJSONObject...
|
0

It would be better to use below PHP function response would be in stdobject

parse_str(file_get_contents("php://input"), $data);

$d = json_decode(json_encode($data));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.