Ios RestKit响应可以';不能反序列化为对象
在使用RestKit的post请求期间,我无法将响应映射回对象 代码如下: 请求:Ios RestKit响应可以';不能反序列化为对象,ios,restkit,restkit-0.20,Ios,Restkit,Restkit 0.20,在使用RestKit的post请求期间,我无法将响应映射回对象 代码如下: 请求: // mapping for the response. response is an object: {"response":"message","success":bool} RKObjectMapping *responseMapping = [RKObjectMapping mappingForClass:[GenericResponse class]]; [responseMapping add
// mapping for the response. response is an object: {"response":"message","success":bool}
RKObjectMapping *responseMapping = [RKObjectMapping mappingForClass:[GenericResponse class]];
[responseMapping addAttributeMappingsFromArray:@[@"success",@"response"]];
responseMapping.setDefaultValueForMissingAttributes = YES;
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:responseMapping pathPattern:@"/authenticate" keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
// mapping for the request body
RKObjectMapping *requestMapping = [RKObjectMapping requestMapping];
[requestMapping addAttributeMappingsFromArray:@[@"username", @"password"]];
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:requestMapping objectClass:[LoginCriteria class] rootKeyPath:nil];
// set up the request
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:@"http://localhost:8080"]];
[manager addResponseDescriptor:responseDescriptor];
[manager addRequestDescriptor:requestDescriptor];
[manager setRequestSerializationMIMEType:@"application/json"];
// set up the LoginCriteria object
LoginCriteria* loginCriteria = [LoginCriteria new];
loginCriteria.password = @"test";
loginCriteria.username = @"test";
// make the request
[manager postObject:loginCriteria path:@"/authenticate" parameters:nil
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
GenericResponse *genericResponse = (GenericResponse*)mappingResult;
NSLog(@"logged in: %@", [mappingResult array]);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(@"login failed");
}];
一般性答复.h:
@interface GenericResponse : NSObject
@property (nonatomic) Boolean* success;
@property (nonatomic, copy) NSString* response;
@end
日志:
从日志中,我感到奇怪的是,RestKit似乎期望对LoginCriteria对象的响应进行反序列化,但当它正确地获取GenericResponse对象时“失败”,这当然是正确的
非常感谢您的帮助 我对RestKit也有同样的问题。
解决方法是为我作为响应发布的对象添加映射。我深入研究了RestKit代码,在
RKMapperOperation.m
中的mapObject
函数中找到了以下代码片段:
if (NO == [[self.targetObject class] isSubclassOfClass:objectMapping.objectClass]) {
if ([_mappingsDictionary count] == 1) {
NSString *errorMessage = [NSString stringWithFormat:
@"Expected an object mapping for class of type '%@', provider returned one for '%@'",
NSStringFromClass([self.targetObject class]), NSStringFromClass(objectMapping.objectClass)];
[self addErrorWithCode:RKMappingErrorTypeMismatch message:errorMessage keyPath:keyPath userInfo:nil];
return nil;
} else {
// There is more than one mapping present. We are likely mapping secondary key paths to new objects
destinationObject = [self objectWithMapping:mapping andData:mappableObject];
}
}
第一个if
语句检查以确保targetObject
(请求对象)具有属于objectMapping.objectClass
(响应对象)层次结构中的类类型。由于我的请求和响应对象不同,这当然会失败。我在那一行设置了一个断点来证明这一点。以下是我检查时打印的内容:
(lldb) po self.targetObject
(id) $1 = 0x09fb54d0 <LoginCriteria: 0x9fb54d0>
(lldb) po objectMapping.objectClass
(Class) $2 = 0x00162c58 GenericResponse
(lldb)po self.targetObject
(id)$1=0x09fb54d0
(lldb)po objectMapping.objectClass
(类别)$2=0x00162c58一般响应
如您所见,它们属于不同的类型,因此如果成功,函数将返回nil,从而使响应未映射。我只是替换了返回nil
withdestinationObject=[self-objectWithMapping:mapping和data:mappableObject]代码>,一切正常
我对这个解决方案很不满意,因为我觉得RestKit的作者并不打算发送和接收不同的对象。因此,这是一个黑客。直到a)我听到一个更好的解决方案,或者b)RestKit的作者自己(或者接受我的:)做了这个更改,我才回答这个问题。谢谢你对你问题的回答,因为它引导我找到了正确的方向,来解决这个问题,而不是修改核心代码
从他的文档中,在核心数据Post/Put中处理多个根对象的一节中,他提到,如果要发布一种类型的对象,但在响应中接收另一种类型的对象,则必须在请求操作中nil
输出targetObject
。他的文档中缺少完整的示例,因此下面是我使用的代码块:
RKManagedObjectRequestOperation *operation = [RKObjectManager.sharedManager appropriateObjectRequestOperationWithObject: objectToBePOSTed method:RKRequestMethodPOST path: path parameters: params];
operation.targetObject = nil;
[operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
//handle success
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
//handle failure
}];
[RKObjectManager.sharedManager enqueueObjectRequestOperation:operation];
~Happy Holidays谢谢您的回复。我只是尝试添加LoginCriteria对象作为响应描述符,但得到了相同的错误。这就是你建议做的吗?是的,就像你在一般回答中添加的一样。嗯,我就是这么做的,但对我来说不起作用。我仔细查看了它,发现添加了两个响应描述符,但在mapObject
中执行反序列化过程时,[\u mappingsDictionary count]
始终为1。是否检查了映射中的对象?嗯,你用的是什么版本?多亏了你的回答,我的假期变得更快乐了。谢谢你!我也有同样的问题,@AngeloS提供了下面的解决方案。当使用postObject方法时,RestKit假设响应应该映射回与发布的对象相同的类,而不管您在对象管理器中注册了什么响应描述符。我不认为这是一个很好的假设,因为在许多情况下,返回整个对象的副本而不是像代码中那样简单的成功消息是没有意义的!同意。当我需要的是真/假时,我不确定是否要在线路上放置潜在的大量数据。在考虑移动通信时,这尤其值得关注。
RKManagedObjectRequestOperation *operation = [RKObjectManager.sharedManager appropriateObjectRequestOperationWithObject: objectToBePOSTed method:RKRequestMethodPOST path: path parameters: params];
operation.targetObject = nil;
[operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
//handle success
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
//handle failure
}];
[RKObjectManager.sharedManager enqueueObjectRequestOperation:operation];