Cómo enviar datos json en la solicitud Http usando NSURLRequest

Soy nuevo en Objectivo-c y estoy empezando a poner mucho esfuerzo en la solicitud / respuesta como reciente. Tengo un ejemplo de trabajo que puede llamar a una url (a través de http GET) y analizar el json devuelto.

El ejemplo de trabajo de esto está debajo

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { [responseData setLength:0]; } - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { [responseData appendData:data]; } - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { NSLog([NSString stringWithFormat:@"Connection failed: %@", [error description]]); } - (void)connectionDidFinishLoading:(NSURLConnection *)connection { [connection release]; //do something with the json that comes back ... (the fun part) } - (void)viewDidLoad { [self searchForStuff:@"iPhone"]; } -(void)searchForStuff:(NSString *)text { responseData = [[NSMutableData data] retain]; NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.whatever.com/json"]]; [[NSURLConnection alloc] initWithRequest:request delegate:self]; } 

Mi primera pregunta es: ¿se ampliará este enfoque? ¿O no es asincrónico (es decir, locking el hilo de la interfaz de usuario mientras la aplicación está esperando la respuesta)?

Mi segunda pregunta es: ¿cómo podría modificar la parte de la solicitud de esto para hacer una POST en lugar de GET? ¿Es simplemente modificar HttpMethod como tal?

 [request setHTTPMethod:@"POST"]; 

Y finalmente, ¿cómo agrego un conjunto de datos json a esta publicación como una cadena simple (por ejemplo)

 { "magic":{ "real":true }, "options":{ "happy":true, "joy":true, "joy2":true }, "key":"123" } 

Gracias de antemano

Esto es lo que hago (tenga en cuenta que el JSON que va a mi servidor necesita ser un diccionario con un valor (otro diccionario) para key = question..ie {: question => {dictionary}}):

 NSArray *objects = [NSArray arrayWithObjects:[[NSUserDefaults standardUserDefaults]valueForKey:@"StoreNickName"], [[UIDevice currentDevice] uniqueIdentifier], [dict objectForKey:@"user_question"], nil]; NSArray *keys = [NSArray arrayWithObjects:@"nick_name", @"UDID", @"user_question", nil]; NSDictionary *questionDict = [NSDictionary dictionaryWithObjects:objects forKeys:keys]; NSDictionary *jsonDict = [NSDictionary dictionaryWithObject:questionDict forKey:@"question"]; NSString *jsonRequest = [jsonDict JSONRepresentation]; NSLog(@"jsonRequest is %@", jsonRequest); NSURL *url = [NSURL URLWithString:@"https://xxxxxxx.com/questions"]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0]; NSData *requestData = [jsonRequest dataUsingEncoding:NSUTF8StringEncoding]; [request setHTTPMethod:@"POST"]; [request setValue:@"application/json" forHTTPHeaderField:@"Accept"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setValue:[NSString stringWithFormat:@"%d", [requestData length]] forHTTPHeaderField:@"Content-Length"]; [request setHTTPBody: requestData]; NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:self]; if (connection) { receivedData = [[NSMutableData data] retain]; } 

El receivedData es manejado por:

 NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSDictionary *jsonDict = [jsonString JSONValue]; NSDictionary *question = [jsonDict objectForKey:@"question"]; 

Esto no es 100% claro y tomará algunas relecturas, pero todo debería estar aquí para comenzar. Y por lo que puedo decir, esto es asincrónico. Mi UI no está bloqueada mientras se realizan estas llamadas. Espero que ayude.

Sugeriría usar ASIHTTPRequest

ASIHTTPRequest es un contenedor fácil de usar alrededor de la API de CFNetwork que facilita algunos de los aspectos más tediosos de la comunicación con servidores web. Está escrito en Objective-C y funciona en aplicaciones Mac OS X e iPhone.

Es adecuado realizar solicitudes HTTP básicas e interactuar con servicios basados ​​en REST (GET / POST / PUT / DELETE). La subclase ASIFormDataRequest incluida facilita el envío de datos POST y archivos usando multipart / form-data.


Tenga en cuenta que el autor original suspendió este proyecto. Consulte la publicación siguiente por motivos y alternativas: http://allseeing-i.com/%5Brequest_release%5D ;

Personalmente, soy un gran fanático de AFNetworking

Luché con esto por un tiempo. Ejecutando PHP en el servidor. Este código publicará un json y obtendrá la respuesta json del servidor

 NSURL *url = [NSURL URLWithString:@"http://example.co/index.php"]; NSMutableURLRequest *rq = [NSMutableURLRequest requestWithURL:url]; [rq setHTTPMethod:@"POST"]; NSString *post = [NSString stringWithFormat:@"command1=c1&command2=c2"]; NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding]; [rq setHTTPBody:postData]; [rq setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; NSOperationQueue *queue = [[NSOperationQueue alloc] init]; [NSURLConnection sendAsynchronousRequest:rq queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { if ([data length] > 0 && error == nil){ NSError *parseError = nil; NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError]; NSLog(@"Server Response (we want to see a 200 return code) %@",response); NSLog(@"dictionary %@",dictionary); } else if ([data length] == 0 && error == nil){ NSLog(@"no data returned"); //no data, but tried } else if (error != nil) { NSLog(@"there was a download error"); //couldn't download } }]; 

La mayoría de ustedes ya saben esto, pero estoy publicando esto, solo en el caso, algunos de ustedes todavía están luchando con JSON en iOS6 +.

En iOS6 y posterior, tenemos la clase NSJSONSerialization que es rápida y no tiene dependencia de incluir bibliotecas “externas”.

 NSDictionary *result = [NSJSONSerialization JSONObjectWithData:[resultStr dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil]; 

Esta es la forma en que iOS6 y posterior ahora pueden analizar JSON de manera eficiente. El uso de SBJson también es una implementación previa al ARC y trae consigo esos problemas también si está trabajando en un entorno ARC.

¡Espero que esto ayude!

Aquí hay un gran artículo usando Restkit

Explica sobre la serialización de datos nesteds en JSON y la conexión de los datos a una solicitud HTTP POST.

Desde mi edición a la respuesta de Mike G para modernizar el código fue rechazado 3 a 2 como

Esta edición tenía como objective dirigirse al autor de la publicación y no tiene sentido como una edición. Debería haber sido escrito como un comentario o una respuesta

Estoy reubicando mi edición como una respuesta separada aquí. Esta edición elimina la dependencia JSONRepresentation con NSJSONSerialization como NSJSONSerialization el comentario de Rob con 15 upvotes.

  NSArray *objects = [NSArray arrayWithObjects:[[NSUserDefaults standardUserDefaults]valueForKey:@"StoreNickName"], [[UIDevice currentDevice] uniqueIdentifier], [dict objectForKey:@"user_question"], nil]; NSArray *keys = [NSArray arrayWithObjects:@"nick_name", @"UDID", @"user_question", nil]; NSDictionary *questionDict = [NSDictionary dictionaryWithObjects:objects forKeys:keys]; NSDictionary *jsonDict = [NSDictionary dictionaryWithObject:questionDict forKey:@"question"]; NSLog(@"jsonRequest is %@", jsonRequest); NSURL *url = [NSURL URLWithString:@"https://xxxxxxx.com/questions"]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0]; NSData *requestData = [NSJSONSerialization dataWithJSONObject:dict options:0 error:nil]; //TODO handle error [request setHTTPMethod:@"POST"]; [request setValue:@"application/json" forHTTPHeaderField:@"Accept"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; [request setValue:[NSString stringWithFormat:@"%d", [requestData length]] forHTTPHeaderField:@"Content-Length"]; [request setHTTPBody: requestData]; NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:self]; if (connection) { receivedData = [[NSMutableData data] retain]; } 

El receivedData es manejado por:

 NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil]; NSDictionary *question = [jsonDict objectForKey:@"question"]; 

Aquí hay un ejemplo actualizado que está usando NSURLConnection + sendAsynchronousRequest: (10.7+, iOS 5+), la solicitud “Publicar” sigue siendo la misma que con la respuesta aceptada y se omite aquí en aras de la claridad:

 NSURL *apiURL = [NSURL URLWithString: [NSString stringWithFormat:@"http://www.myserver.com/api/api.php?request=%@", @"someRequest"]]; NSURLRequest *request = [NSURLRequest requestWithURL:apiURL]; // this is using GET, for POST examples see the other answers here on this page [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { if(data.length) { NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; if(responseString && responseString.length) { NSLog(@"%@", responseString); } } }]; 

Puede probar este código para enviar cadena json

 NSData *jsonData = [NSJSONSerialization dataWithJSONObject:ARRAY_CONTAIN_JSON_STRING options:NSJSONWritin*emphasized text*gPrettyPrinted error:NULL]; NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; NSString *WS_test = [NSString stringWithFormat:@"www.test.com?xyz.php&param=%@",jsonString];