Reputation: 165
I have a situation where I POST a JSON string from my iOS code using AFNetworking 2.0 code. My client code looks like this:
NSURL *url = [NSURL URLWithString:BaseURLString];
NSString *jsonString = [[NSString alloc] initWithData:jsonPayloadForProject encoding:NSUTF8StringEncoding];
NSDictionary *parameters = @{@"project": jsonString};
AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] initWithBaseURL:url];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"text/html"];
[manager POST:@"service.php" parameters:parameters success:^(NSURLSessionDataTask *task, id responseObject) {
NSLog(@"%@", [responseObject description]);
} failure:^(NSURLSessionDataTask *task, NSError *error) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"POST JSON for Project Error"
message:[error localizedDescription]
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alertView show];
}];
The JSON looks like this:
{
"Maps" : [
{
"Markers" : [
{
"marker_tag" : -790386438,
"location_y" : 182,
"location_x" : 344
},
{
"marker_tag" : 451496476,
"location_y" : 267,
"location_x" : 150.5
}
],
"image_string" : "EC817509-DE49-4914-840E-5E407571F6AE.jpeg",
"order_num" : 0,
"name" : "Blah1",
"id" : "EC817509-DE49-4914-840E-5E407571F6AE"
},
{
"Markers" : [
{
"marker_tag" : -79601351,
"location_y" : 377,
"location_x" : 486.5,
"image_id" : "Blah2",
"map_id" : "146C1C09-5AE0-4E4C-83C8-B7EAA8F28A9A"
}
],
"image_string" : "146C1C09-5AE0-4E4C-83C8-B7EAA8F28A9A.jpeg",
"order_num" : 0,
"name" : "1st floor",
"id" : "146C1C09-5AE0-4E4C-83C8-B7EAA8F28A9A"
}
],
"longitude" : "-222.222222",
"latitude" : "33.33333"
}
When I read the JSON string on the server in my php code using
$json_str = file_get_contents('php://input');
When I do that, I get the following string:
{ "project" = '{ \n \"Maps\" : [ \n { \n \"Markers\" : [ \n { \n \"marker_tag\n : = -790386438, \n ....
My question is that when I do the following, I get nothing.
$array_str = json_decode($json_str, true);
What is the best way to put that into an array to parse for data? How can I get back the original JSON string I sent from my client?
Upvotes: 1
Views: 742
Reputation: 437582
A couple of issues
Your AFHTTPSessionManager
is using the default AFJSONResponseSerializer
but merely overriding the acceptableContentTypes
. You would only do that if your server code was really returning JSON and failing to specify so in the Content-Type
header.
If the server is really not returning JSON, rather than changing acceptableContentTypes
, you should simply use AFHTTPSessionManager
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
or have the server return JSON and make sure it specifies the correct Content-Type
header:
<?php
$json_str = file_get_contents('php://input');
$json = json_decode($json_str, true);
header('Content-Type: application/json');
$result = array("received" => $json);
echo json_encode($result);
?>
Having done that, I can now simply remove the acceptableContentTypes
line from the client code altogether and continue to use the default AFJSONResponseSerializer
.
The demonstrated mechanism for building parameters
is incorrect. You are creating a JSON dictionary with only one item in it, which itself is a string representation of JSON.
Instead of putting a string representation within the dictionary, I would suggest that you want to put the actual dictionary within the dictionary. So, if you really have a NSData
of the JSON, convert it back to the nested NSDictionary
/NSArray
structure:
NSError *error;
id jsonPayload = [NSJSONSerialization JSONObjectWithData:jsonPayloadData options:0 error:&error];
NSAssert(jsonPayload, @"json parsing error: %@", error);
NSDictionary *parameters = @{@"project": jsonPayload};
Now, most likely, it will be a little silly to create a NSData
using dataWithJSONObject
, only to turn around and extract it back out, but rather you'd just use that original NSDictionary
within parameters
, but hopefully this illustrates the point.
So, pulling that all together, assuming you change the server code to return properly formatted JSON response, as outlined above, the client code now becomes:
NSError *error;
id jsonPayload = [NSJSONSerialization JSONObjectWithData:jsonPayloadData options:0 error:&error];
NSAssert(jsonPayload, @"json parsing error: %@", error);
NSDictionary *parameters = @{@"project": jsonPayload};
AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc] initWithBaseURL:url];
manager.requestSerializer = [AFJSONRequestSerializer serializer];
// manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"text/html"];
[manager POST:@"service.php" parameters:parameters success:^(NSURLSessionDataTask *task, id responseObject) {
NSLog(@"%@", [responseObject description]);
} failure:^(NSURLSessionDataTask *task, NSError *error) {
NSLog(@"error=%@", error);
}];
If you do that, you will successfully send your JSON request to the server, it will be parsed, inserted into a new associative array, converted back to JSON and returned to the client app, which will use the default AFJSONResponseSerializer
to parse it and log it.
Upvotes: 1