简体   繁体   English

如何使用NSURLRequest在Http请求中发送json数据

[英]How to send json data in the Http request using NSURLRequest

I'm new to objective-c and I'm starting to put a great deal of effort into request/response as of recent. 我是Objective-c的新手,我开始在最近的请求/响应中投入大量精力。 I have a working example that can call a url (via http GET) and parse the json returned. 我有一个可以调用url(通过http GET)并解析返回的json的工作示例。

The working example of this is below 这个工作的例子如下

- (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];
}

My first question is - will this approach scale up? 我的第一个问题是 - 这种方法会扩大吗? Or is this not async (meaning I block the UI thread while the app is waiting for the response) 或者这不是异步(意味着我在应用程序等待响应时阻止UI线程)

My second question is - how might I modify the request part of this to do a POST instead of GET? 我的第二个问题是 - 如何修改此请求部分以执行POST而不是GET? Is it simply to modify the HttpMethod like so? 它只是简单地修改HttpMethod吗?

[request setHTTPMethod:@"POST"];

And finally - how do I add a set of json data to this post as a simple string (for example) 最后 - 如何将一组json数据作为简单字符串添加到此帖子中(例如)

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

Thank you in advance 先感谢您

Here's what I do (please note that the JSON going to my server needs to be a dictionary with one value (another dictionary) for key = question..ie {:question => { dictionary } } ): 这就是我的工作(请注意,进入我服务器的JSON需要是一个带有一个值的字典(另一个字典),用于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];
}

The receivedData is then handled by: 然后,receiveData由以下方式处理:

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

This isn't 100% clear and will take some re-reading, but everything should be here to get you started. 这不是100%明确的,需要重新阅读,但一切都应该在这里让你开始。 And from what I can tell, this is asynchronous. 从我所知道的,这是异步的。 My UI is not locked up while these calls are made. 在进行这些调用时,我的UI未被锁定。 Hope that helps. 希望有所帮助。

I struggled with this for a while. 我挣扎了一段时间。 Running PHP on the server. 在服务器上运行PHP。 This code will post a json and get the json reply from the server 此代码将发布一个json并从服务器获取json回复

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

     }
 }];

I would suggest to use ASIHTTPRequest 我建议使用ASIHTTPRequest

ASIHTTPRequest is an easy to use wrapper around the CFNetwork API that makes some of the more tedious aspects of communicating with web servers easier. ASIHTTPRequest是一个易于使用的CFNetwork API包装器,它使与Web服务器通信的一些更繁琐的方面更容易。 It is written in Objective-C and works in both Mac OS X and iPhone applications. 它是用Objective-C编写的,适用于Mac OS X和iPhone应用程序。

It is suitable performing basic HTTP requests and interacting with REST-based services (GET / POST / PUT / DELETE). 它适用于执行基本HTTP请求并与基于REST的服务(GET / POST / PUT / DELETE)交互。 The included ASIFormDataRequest subclass makes it easy to submit POST data and files using multipart/form-data. 包含的ASIFormDataRequest子类可以使用multipart / form-data轻松提交POST数据和文件。


Please note, that the original author discontinued with this project. 请注意,原作者已停止使用此项目。 See the followring post for reasons and alternatives: http://allseeing-i.com/%5Brequest_release%5D ; 请参阅以下帖子了解原因和替代方案: http ://allseeing-i.com/%5Brequest_release%5D;

Personally I am a big fan of AFNetworking 就个人而言,我是AFNetworking的忠实粉丝

Most of you already know this by now, but I am posting this, just incase, some of you are still struggling with JSON in iOS6+. 你们大多数人现在已经知道了这一点,但是我发布了这个,只是因为你们中的一些人仍在为iOS6 +中的JSON苦苦挣扎。

In iOS6 and later, we have the NSJSONSerialization Class that is fast and has no dependency on including "outside" libraries. 在iOS6及更高版本中,我们拥有NSJSONSerialization类 ,它快速且不依赖于包含“外部”库。

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

This is the way iOS6 and later can now parse JSON efficiently.The use of SBJson is also pre-ARC implementation and brings with it those issues too if you are working in an ARC environment. 这是iOS6及更高版本现在可以有效解析JSON的方式.SBJson的使用也是ARC之前的实现,如果您在ARC环境中工作,也会带来这些问题。

I hope this helps! 我希望这有帮助!

Here is a great article using Restkit 这是一篇使用Restkit的精彩文章

It explains on serializing nested data into JSON and attaching the data to a HTTP POST request. 它解释了将嵌套数据序列化为JSON并将数据附加到HTTP POST请求。

Since my edit to Mike G's answer to modernize the code was rejected 3 to 2 as 由于我编辑迈克G的代码现代化的答案被拒绝为3比2

This edit was intended to address the author of the post and makes no sense as an edit. 此编辑旨在解决帖子的作者,并且没有任何意义作为编辑。 It should have been written as a comment or an answer 它应该被写成评论或答案

I'm reposting my edit as a separate answer here. 我在这里将我的编辑作为单独的答案重新发布。 This edit removes the JSONRepresentation dependency with NSJSONSerialization as Rob's comment with 15 upvotes suggests. 此编辑使用NSJSONSerialization删除JSONRepresentation依赖关系,因为Rob的评论有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];
    }

The receivedData is then handled by: 然后,receiveData由以下方式处理:

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

Here's an updated example that is using NSURLConnection +sendAsynchronousRequest: (10.7+, iOS 5+), The "Post" request remains the same as with the accepted answer and is omitted here for the sake of clarity: 这是一个使用NSURLConnection + sendAsynchronousRequest的更新示例:(10.7 +,iOS 5+),“Post”请求与接受的答案保持一致,为了清楚起见,此处省略:

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);
         }
     }
}];

You can try this code for send json string 您可以尝试使用此代码发送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];

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM