I know that there are similar questions posted as I have read though most all of them and still am having problems. I am trying to send JSON data to my server, but I do not think the JSON data is being received. I'm just not sure what I am missing. Below is my code...
Method to send data to server.
- (void)saveTrackToCloud
{
NSData *jsonData = [self.track jsonTrackDataForUploadingToCloud]; // Method shown below.
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
NSLog(@"%@", jsonString); // To verify the jsonString.
NSMutableURLRequest *postRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:http://www.myDomain.com/myscript.php] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60];
[postRequest setHTTPMethod:@"POST"];
[postRequest setValue:@"application/json" forHTTPHeaderField:@"Accept"];
[postRequest setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[postRequest setValue:[NSString stringWithFormat:@"%d", [jsonData length]] forHTTPHeaderField:@"Content-Length"];
[postRequest setHTTPBody:jsonData];
NSURLResponse *response = nil;
NSError *requestError = nil;
NSData *returnData = [NSURLConnection sendSynchronousRequest:postRequest returningResponse:&response error:&requestError];
if (requestError == nil) {
NSString *returnString = [[NSString alloc] initWithBytes:[returnData bytes] length:[returnData length] encoding:NSUTF8StringEncoding];
NSLog(@"returnString: %@", returnString);
} else {
NSLog(@"NSURLConnection sendSynchronousRequest error: %@", requestError);
}
}
Method jsonTrackDataForUploadingToCloud
-(NSData *)jsonTrackDataForUploadingToCloud
{
// NSDictionary for testing.
NSDictionary *trackDictionary = [NSDictionary dictionaryWithObjectsAndKeys:@"firstValue", @"firstKey", @"secondValue", @"secondKey", @"thirdValue", @"thirdKey", nil];
if ([NSJSONSerialization isValidJSONObject:trackDictionary]) {
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:trackDictionary options:NSJSONWritingPrettyPrinted error:&error];
if (error == nil && jsonData != nil) {
return jsonData;
} else {
NSLog(@"Error creating JSON data: %@", error);
return nil;
}
} else {
NSLog(@"trackDictionary is not a valid JSON object.");
return nil;
}
}
And here is my php.
<?php
var_dump($_POST);
exit;
?>
The output that I receive from NSLog(@"returnString: %@", returnString);
is...
returnString: array(0) {
}
In your PHP, you're grabbing the $_POST
variable, which is for application/x-www-form-urlencoded
content type (or other standard HTTP requests). If you're grabbing JSON, though, you should retrieve the raw data:
<?php
// read the raw post data
$handle = fopen("php://input", "rb");
$raw_post_data = '';
while (!feof($handle)) {
$raw_post_data .= fread($handle, 8192);
}
fclose($handle);
echo $raw_post_data;
?>
More likely, though, you want to take that JSON $raw_post_data
, decode the JSON into an associative array ($request
, in my example below), and then build an associative array $response
on the basis of what was in the request, and then encode it as JSON and return it. I'll also set the content-type
of the response to make it clear it's a JSON response. As a random example, see:
<?php
// read the raw post data
$handle = fopen("php://input", "rb");
$raw_post_data = '';
while (!feof($handle)) {
$raw_post_data .= fread($handle, 8192);
}
fclose($handle);
// decode the JSON into an associative array
$request = json_decode($raw_post_data, true);
// you can now access the associative array, $request
if ($request['firstKey'] == 'firstValue') {
$response['success'] = true;
} else {
$response['success'] = false;
}
// I don't know what else you might want to do with `$request`, so I'll just throw
// the whole request as a value in my response with the key of `request`:
$response['request'] = $request;
$raw_response = json_encode($response);
// specify headers
header("Content-Type: application/json");
header("Content-Length: " . strlen($raw_response));
// output response
echo $raw_response;
?>
This isn't a terribly useful example (just checking to see if the value associated with firstKey
was 'firstValue'
), but hopefully it illustrates the idea of how to parse the request and create the response.
A couple of other asides:
You might want to include the checking of the status code of the response (since from NSURLConnection
perspective, some random server error, like 404 - page not found) will not be interpreted as an error, so check the response codes.
You'd obviously probably want to use NSJSONSerialization
to parse the response:
[NSURLConnection sendAsynchronousRequest:postRequest queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (error) {
NSLog(@"NSURLConnection sendAsynchronousRequest error = %@", error);
return;
}
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode];
if (statusCode != 200) {
NSLog(@"Warning, status code of response was not 200, it was %d", statusCode);
}
}
NSError *parseError;
NSDictionary *returnDictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
if (returnDictionary) {
NSLog(@"returnDictionary = %@", returnDictionary);
} else {
NSLog(@"error parsing JSON response: %@", parseError);
NSString *returnString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"returnString = %@", returnString);
}
}
I might suggest that you should use sendAsynchronousRequest
, as shown above, rather than synchronous request, because you should never do synchronous requests from the main queue.
My example PHP is doing minimal checking of the Content-type
of the request, etc. So you might want to do more robust error handling.