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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4456966/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 17:41:45  来源:igfitidea点击:

How to send json data in the Http request using NSURLRequest

iphoneobjective-ccocoa-touchjsonnsurlrequest

提问by Toran Billups

I'm new to objective-c and I'm starting to put a great deal of effort into request/response as of recent. I have a working example that can call a url (via http GET) and parse the json returned.

我是objective-c的新手,最近我开始在请求/响应上投入大量精力。我有一个可以调用 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? Is it simply to modify the HttpMethod like so?

我的第二个问题是 - 我如何修改请求部分来执行 POST 而不是 GET?是不是简单的像这样修改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

先感谢您

回答by Mike G

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..i.e. {: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:

然后通过以下方式处理收到的数据:

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. And from what I can tell, this is asynchronous. My UI is not locked up while these calls are made. Hope that helps.

这不是 100% 清楚,需要重新阅读,但一切都应该在这里让你开始。据我所知,这是异步的。进行这些调用时,我的 UI 没有被锁定。希望有帮助。

回答by user3344717

I struggled with this for a while. Running PHP on the server. This code will post a json and get the json reply from the server

我为此挣扎了一段时间。在服务器上运行 PHP。此代码将发布一个 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

     }
 }];

回答by vikingosegundo

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. It is written in Objective-C and works in both Mac OS X and iPhone applications.

It is suitable performing basic HTTP requests and interacting with REST-based services (GET / POST / PUT / DELETE). The included ASIFormDataRequest subclass makes it easy to submit POST data and files using multipart/form-data.

ASIHTTPRequest 是一个围绕 CFNetwork API 的易于使用的包装器,它使与 Web 服务器通信的一些更乏味的方面变得更容易。它是用 Objective-C 编写的,适用于 Mac OS X 和 iPhone 应用程序。

它适用于执行基本的 HTTP 请求并与基于 REST 的服务(GET / POST / PUT / DELETE)交互。包含的 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 的忠实粉丝

回答by tony.stack

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 Classthat 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!

我希望这有帮助!

回答by Steve Moser

Since my edit to Mike G's answer to modernize the code was rejected 3 to 2 as

由于我对 Mike 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 JSONRepresentationdependency with NSJSONSerializationas Rob's comment with 15 upvotes suggests.

我在这里重新发布我的编辑作为单独的答案。此编辑删除了JSONRepresentation依赖项,NSJSONSerialization正如 Rob 的评论与 15 票所建议的那样。

    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:

然后通过以下方式处理收到的数据:

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

回答by cevaris

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 请求。

回答by Jayesh Mardiya

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

回答by auco

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+),“发布”请求与接受的答案保持相同,为清楚起见,此处省略:

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