【问题标题】:How to send json data in the Http request using NSURLRequest如何使用 NSURLRequest 在 Http 请求中发送 json 数据
【发布时间】:2011-05-26 07:28:54
【问题描述】:

我是 Objective-c 的新手,最近我开始在请求/响应方面投入大量精力。我有一个可以调用 url(通过 http GET)并解析返回的 json 的工作示例。

这个工作的例子如下

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

我的第一个问题是 - 这种方法会扩大规模吗?或者这不是异步的(意味着我在应用等待响应时阻塞了 UI 线程)

我的第二个问题是 - 我如何修改请求部分以执行 POST 而不是 GET?难道就这么简单地修改HttpMethod吗?

[request setHTTPMethod:@"POST"];

最后 - 我如何将一组 json 数据作为一个简单的字符串添加到这篇文章中(例如)

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

提前谢谢你

【问题讨论】:

标签: iphone objective-c cocoa-touch json nsurlrequest


【解决方案1】:

我建议使用ASIHTTPRequest

ASIHTTPRequest 是一个易于使用的 CFNetwork API 的包装器 使一些更繁琐的方面 与 Web 服务器的通信 更轻松。它是用 Objective-C 编写的 并且适用于 Mac OS X 和 iPhone 应用程序。

适合执行基本的HTTP 请求并与之交互 基于 REST 的服务(GET / POST / PUT / 删除)。包含的 ASIFormDataRequest 子类使它 易于提交 POST 数据和文件 使用 multipart/form-data。


请注意,原作者已停止使用此项目。原因和替代方法见以下帖子:http://allseeing-i.com/%5Brequest_release%5D;

我个人是AFNetworking的忠实粉丝

【讨论】:

    【解决方案2】:

    这就是我要做的(请注意,转到我的服务器的 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];
    }
    

    receivedData 然后被处理:

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

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

    【讨论】:

    • 一切看起来都不错,除了这一行 [dict objectForKey:@"user_question"], nil]; -- dict 未在您的示例中声明。这只是一个简单的字典还是特别的东西?
    • 很抱歉。是的,“dict”只是我从 iOS 用户文档中加载的一个简单字典。
    • 这是使用NSDictionary实例方法JSONRepresentation。我可能会建议我使用NSJSONSerialization 类方法dataWithJSONObject,而不是json-framework
    • 通过[[NSNumber numberWithUnsignedInt:requestData.length] stringValue]这样的NSNumber将NSUInteger转换为NSString效率更高。
    • @MikeG 修复了代码示例中一个长期存在且迄今为止未被注意到的错误。抱歉,编辑您的帖子;)
    【解决方案3】:

    这是一篇使用Restkit的精彩文章

    它解释了将嵌套数据序列化为 JSON 并将数据附加到 HTTP POST 请求。

    【讨论】:

      【解决方案4】:

      你们中的大多数人现在已经知道这一点,但我发布这个,以防万一,你们中的一些人仍在为 iOS6+ 中的 JSON 苦苦挣扎。

      在 iOS6 及更高版本中,我们有 NSJSONSerialization Class,它速度很快,并且不依赖于包含“外部”库。

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

      这是 iOS6 和更高版本现在可以有效解析 JSON 的方式。SBJson 的使用也是 ARC 之前的实现,如果您在 ARC 环境中工作,也会带来这些问题。

      我希望这会有所帮助!

      【讨论】:

        【解决方案5】:

        这是一个使用 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);
                 }
             }
        }];
        

        【讨论】:

        • 问题是关于 POST 的
        • 不,问题的第一部分是关于异步性的,这里没有答案可以回答这个问题。为反对票喝彩。
        【解决方案6】:

        我为此苦苦挣扎了一段时间。在服务器上运行 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
        
             }
         }];
        

        【讨论】:

        • content type = "application/x-www-form-urlencoded" 成功了。谢谢
        • 不错的答案。我在我的案例中使用了“application/json”
        【解决方案7】:

        由于我对 Mike G 对代码现代化的回答的编辑被 3 比 2 拒绝为

        此编辑旨在解决帖子的作者,并没有 感觉是一种编辑。它应该写成评论或 回答

        我在这里将我的编辑作为单独的答案重新发布。此编辑删除了 JSONRepresentationNSJSONSerialization 的依赖关系,正如 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];
            }
        

        receivedData 然后被处理:

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

        【讨论】:

          【解决方案8】:

          你可以试试这个代码来发送 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];
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多