Objective c 使用AFNetworking通过HTTP身份验证获取JSON

Objective c 使用AFNetworking通过HTTP身份验证获取JSON,objective-c,afnetworking,Objective C,Afnetworking,我试图从我的hudson url地址获取JSON,并使用HTTP身份验证对我的(Mac OS X)应用程序进行身份验证 下面是我正在使用的示例: // AppDelegate.m - (void) doSomething { [[CommAPIClient sharedClient] getPath:@"/computer/api/json" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseOb

我试图从我的hudson url地址获取JSON,并使用HTTP身份验证对我的(Mac OS X)应用程序进行身份验证

下面是我正在使用的示例:

// AppDelegate.m
- (void) doSomething {
    [[CommAPIClient sharedClient] getPath:@"/computer/api/json" parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
        NSLog(@"Name: %@", [responseObject valueForKeyPath:@"totalExecutors"]);

    } failure:nil];
}

// CommAPIClient.m
+ (CommAPIClient *) sharedClient {
    static CommAPIClient *_sharedClient = nil;
    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{
        AppDelegate *appDelegate = (AppDelegate *)[[NSApplication sharedApplication] delegate];
        _sharedClient = [[self alloc] initWithBaseURL:[NSURL URLWithString:    [appDelegate.hudsonTextField stringValue]]];
    });
    return _sharedClient;
}

- (id) initWithBaseURL:(NSURL *)url {
    self = [super initWithBaseURL:url];
    if (self){
        [self registerHTTPOperationClass:[AFJSONRequestOperation class]];

        AppDelegate *appDelegate = (AppDelegate *)[[NSApplication sharedApplication] delegate];
        userName = [appDelegate.userTextField stringValue];
        password = [appDelegate.passwdTextField stringValue];

        [self setAuthorizationHeaderWithUsername:userName password:password];
        [self setDefaultHeader:@"Accept" value:@"application/json"];
    }
    return self;
}
我想让计算机的列表显示在我的下拉列表中,但这两行不能同时工作: [self-setAuthorizationHeaderWithUsername:userName密码:password]; [self-setDefaultHeader:@“接受”值:@“应用程序/json”]

如果我只使用第一行,我的身份验证工作正常,但我收到该错误,因为我试图获取密钥:

2012-02-03 02:43:57.542 HudsonSlave[7523:707] An uncaught exception was raised
2012-02-03 02:43:57.542 HudsonSlave[7523:707] [<NSConcreteData 0x100850000> valueForUndefinedKey:]: this class is not key value coding-compliant for the key totalExecutors.

2012-02-03 02:43:57.623 HudsonSlave[7523:707] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<NSConcreteData 0x100850000> valueForUndefinedKey:]: this class is not key value coding-compliant for the key totalExecutors.'
2012-02-03 02:43:57.542哈德逊奴隶[7523:707]引发了未捕获的异常
2012-02-03 02:43:57.542 Hudson Slave[7523:707][valueForUndefinedKey:]:此类不符合key totalExecutors的键值编码。
2012-02-03 02:43:57.623 Hudson Slave[7523:707]***由于未捕获的异常“NSUnknownKeyException”而终止应用程序,原因:“[valueForUndefinedKey:]:此类不符合密钥totalExecutors的键值编码。”
如果使用第二行,我的身份验证将返回错误403

有人能帮忙解决这个问题吗

感谢并为英语中的任何错误道歉

蒂亚戈

预期的内容类型{(“text/javascript”、“application/json”、“text/json”)},已获取application/javascript

正如错误所说,请求期望的是
text/javascript
application/json
text/json
,但服务器发送了
application/javascript
(这是一种不正确的json mime类型)


让服务器以正确的mime类型响应,或者(可能更容易)手动更改
AFJSONRequestOperation
中指定哪些mime类型可访问的行。有一种不太老练的替代方法可以用来更改涉及子类化的库代码,但在您的情况下,这可能比它的价值要麻烦得多。

我在Flickr API中遇到了这个问题,并最终将
AFJSONRequestOperation
子类化,结果证明这是微不足道的。只需重写类方法
defaultAcceptableContentTypes
,例如:

+ (NSSet *)defaultAcceptableContentTypes;
{
    return [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", @"text/plain", nil];
}
然后在我的AFHTTPClient子类中,我只是将我的子类注册为默认的HTTP操作类:

[self registerHTTPOperationClass:[CCFFlickrJSONRequestOperation class]];
更新2013-09-09 14-52-47:


方法名称现在是
+(NSSet*)acceptableContentTypes

如果它是一次性的,而不是对整个AFJSONRequestOperation对象进行子类化,则您可以直接将可接受的内容类型设置为所需的任何类型:

AFJSONRequestOperation *operation = blah blah blah

 [operation setAcceptableContentTypes:[NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", @"text/plain",@"text/html", nil]];

[operation start];

实际上,您现在可以轻松添加更多内容类型:

[AFHTTPRequestOperation addAcceptableContentTypes:[NSSet setWithObjects:@"text/html", nil]];

从AFNetworking 2.0开始,序列化不再是RequestOperation类的一部分,而是委托给序列化程序类。如果您使用2.0,您希望执行类似的操作(一般来说,我认为扩展acceptableContentTypes而不是替换它是最好的解决方案-您永远不知道它在未来的AFNetworking SDK版本中将具有什么基本值):


如果您决定直接使用AFHTTPRequestOperation对象,只需将“requestManager.responseSerializer”替换为“myOperationObject.responseSerializer”。

当您同时使用这两行时会发生什么情况?@mattt,错误告诉我缺少内容类型,因此,我添加了第三行:[self-setDefaultHeader:@“content type”值:@“application/json”];错误为:error Domain=com.alamofire.networking.error Code=-1016“预期内容类型{(“text/javascript”、“application/json”、“text/json”)},got application/javascript“UserInfo=0x100513190{NSLocalizedDescription=预期内容类型{(“text/javascript”、“application/json”、“text/json”))},获得了application/javascript,nserrorfailingurkey=}只是一个旁注:您不需要在
AFHTTPCLient
中设置
内容类型
标题。这将根据请求参数的序列化方式自动设置。在尝试了大量解决方案之后,将AFJSONRequestOperation子类化并重写defaultAcceptableContentTypes是最干净、更好的解决方法!非常感谢。在
AFNetworking 1.0RC1
中,此方法名称已更改为
+(NSSet*)acceptableContentTypes
侧注:有时还需要添加@“text/html”setAcceptableContentTypes,AFNetworking 1.1中似乎不存在良好的问题,Shmidt。
AFHTTPRequestOperationManager *requestManager = [AFHTTPRequestOperationManager manager];

NSMutableSet *contentTypes = [requestManager.responseSerializer.acceptableContentTypes mutableCopy];
[contentTypes addObject:@"text/html"];
[contentTypes addObject:@"text/plain"];
// ... etc ...
requestManager.responseSerializer.acceptableContentTypes = [contentTypes copy];