如何在 Restkit 中映射自定义错误键?
How do I map custom error keys in Restkit?
当用户在我们的服务器上成功注册时,它会返回 200 状态代码和 JSON 有效负载,如下所示:
{
"error": null,
"result": {
"auth": {
"created_utc": 1420740197,
"device_token": "rQZJddrbD5tyEpznb8bVKeGlHqRNGyvOgDR;tQJBkpkfAXO6DQ4lNiG17lzu6IDc0hVBfR3RrN9o0txRQIYAa6fnf5d9LNaSRDMk9LrplgkITuMC37v;;;rvG35CJvV7dWZ5TQVYUWeHwAABvKvzTRpSDw5Qg9jQrmiUHLZptegFY=76421420740197"
},
"display_name": "a",
"email": "a@a.com",
"user_id": 7642,
"username": "a"
}
}
但是如果 a@a.com 尝试再次注册,它会返回一个 400 状态代码和一个 JSON 负载,如下所示:
{
"error": {
"code": 805,
"message": "there is another user with that username"
},
"result": null
}
我尝试映射错误,这样当 Restkit return 出现错误时,我会收到消息和代码。这些是我尝试这样做的方法:
RKObjectMapping *errorMapping = [RKObjectMapping mappingForClass:[RKErrorMessage class]];
[errorMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"error.message" toKeyPath:@"errorMessage"]];
RKResponseDescriptor *errorDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:errorMapping method:RKRequestMethodAny pathPattern:nil keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassClientError)];
[self.objectManager addResponseDescriptor:errorDescriptor];
这显然只是将错误的消息部分发送到 return,输出为:
Error Domain=org.restkit.RestKit.ErrorDomain Code=1004 "there is another user with that username" UserInfo=0x7feefcf8a730 {RKObjectMapperErrorObjectsKey=(
"there is another user with that username"
), NSLocalizedDescription=there is another user with that username}
然后我尝试制作 RKErrorMessage 的子类:
#import "RKErrorMessage.h"
@interface TAG_RKErrorMessage : RKErrorMessage
@property (strong, nonatomic) NSNumber *errorCode;
@end
并将映射更改为:
RKObjectMapping *errorMapping = [RKObjectMapping mappingForClass:[TAG_RKErrorMessage class]];
[errorMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"error.message" toKeyPath:@"errorMessage"]];
[errorMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"error.code" toKeyPath:@"errorCode"]];
这导致了完全相同的输出:
Error Domain=org.restkit.RestKit.ErrorDomain Code=1004 "there is another user with that username" UserInfo=0x7fa16c627ce0 {RKObjectMapperErrorObjectsKey=(
"there is another user with that username"
), NSLocalizedDescription=there is another user with that username}
所以最后我尝试了这个映射,至少尝试让字典显示为 NSError
的 userInfo
:
的 RKObjectMapperErrorObjectsKey
RKObjectMapping *errorMapping = [RKObjectMapping mappingForClass:[RKErrorMessage class]];
[errorMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"error" toKeyPath:@"errorMessage"]];
这导致了这个输出:
Error Domain=org.restkit.RestKit.ErrorDomain Code=1004 "<null>" UserInfo=0x7ff8abe678e0 {RKObjectMapperErrorObjectsKey=(
(null)
), NSLocalizedDescription=<null>}
现在我卡在了这一点上。我如何映射服务器错误响应的键,以便我可以访问 returned 的 code
以及作为两个单独值的 message
?
您可能已经正确映射了 TAG_RKErrorMessage 实例。您是否尝试从给定的 NSError 中提取它?您可以使用 RKObjectMapperErrorObjectsKey 作为 NSError 的 userInfo 字典上的键来获取所有映射错误消息的数组:
NSArray* objectMapperErrorObjectsArray = [error.userInfo objectForKey:RKObjectMapperErrorObjectsKey];
然后您可以遍历该数组以检查每个错误是否符合您要响应的条件,例如,如果您想要使用错误消息 "Invalid token" 响应 403 响应代码,您可以这样做:
NSArray* objectMapperErrorObjectsArray = [error.userInfo objectForKey:RKObjectMapperErrorObjectsKey];
for (RKErrorMessage* objectMapperErrorObject in objectMapperErrorObjectsArray)
{
if ([objectMapperErrorObject.errorMessage isEqual:@"Invalid token"])
{
if (operation.HTTPRequestOperation.response.statusCode == 403)
{
//Code to handle a 403 response status code when error message is "Invalid token".
}
}
}
提示:如果你想使用内置的RKErrorMessage
而不创建任何子类,你可以将所有错误JSON属性映射到RKErrorMessage.userInfo
这样:
Objective-C:
RKObjectMapping *errorMapping = [RKObjectMapping mappingForClass:[RKErrorMessage class]];
[errorMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:nil toKeyPath:@"userInfo"]];
RKResponseDescriptor *errorDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:errorMapping method:RKRequestMethodAny pathPattern:nil keyPath:"error" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassClientError)];
Swift:
let errorMapping = RKObjectMapping(forClass: RKErrorMessage.self);
errorMapping.addPropertyMapping(RKAttributeMapping(fromKeyPath: nil, toKeyPath: "userInfo"));
let errorResponseDescriptor = RKResponseDescriptor(
mapping: errorMapping,
method: RKRequestMethod.Any,
pathPattern: nil,
keyPath: "error",
statusCodes: RKStatusCodeIndexSetForClass(UInt(RKStatusCodeClassClientError)))
);
当用户在我们的服务器上成功注册时,它会返回 200 状态代码和 JSON 有效负载,如下所示:
{
"error": null,
"result": {
"auth": {
"created_utc": 1420740197,
"device_token": "rQZJddrbD5tyEpznb8bVKeGlHqRNGyvOgDR;tQJBkpkfAXO6DQ4lNiG17lzu6IDc0hVBfR3RrN9o0txRQIYAa6fnf5d9LNaSRDMk9LrplgkITuMC37v;;;rvG35CJvV7dWZ5TQVYUWeHwAABvKvzTRpSDw5Qg9jQrmiUHLZptegFY=76421420740197"
},
"display_name": "a",
"email": "a@a.com",
"user_id": 7642,
"username": "a"
}
}
但是如果 a@a.com 尝试再次注册,它会返回一个 400 状态代码和一个 JSON 负载,如下所示:
{
"error": {
"code": 805,
"message": "there is another user with that username"
},
"result": null
}
我尝试映射错误,这样当 Restkit return 出现错误时,我会收到消息和代码。这些是我尝试这样做的方法:
RKObjectMapping *errorMapping = [RKObjectMapping mappingForClass:[RKErrorMessage class]];
[errorMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"error.message" toKeyPath:@"errorMessage"]];
RKResponseDescriptor *errorDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:errorMapping method:RKRequestMethodAny pathPattern:nil keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassClientError)];
[self.objectManager addResponseDescriptor:errorDescriptor];
这显然只是将错误的消息部分发送到 return,输出为:
Error Domain=org.restkit.RestKit.ErrorDomain Code=1004 "there is another user with that username" UserInfo=0x7feefcf8a730 {RKObjectMapperErrorObjectsKey=(
"there is another user with that username"
), NSLocalizedDescription=there is another user with that username}
然后我尝试制作 RKErrorMessage 的子类:
#import "RKErrorMessage.h"
@interface TAG_RKErrorMessage : RKErrorMessage
@property (strong, nonatomic) NSNumber *errorCode;
@end
并将映射更改为:
RKObjectMapping *errorMapping = [RKObjectMapping mappingForClass:[TAG_RKErrorMessage class]];
[errorMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"error.message" toKeyPath:@"errorMessage"]];
[errorMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"error.code" toKeyPath:@"errorCode"]];
这导致了完全相同的输出:
Error Domain=org.restkit.RestKit.ErrorDomain Code=1004 "there is another user with that username" UserInfo=0x7fa16c627ce0 {RKObjectMapperErrorObjectsKey=(
"there is another user with that username"
), NSLocalizedDescription=there is another user with that username}
所以最后我尝试了这个映射,至少尝试让字典显示为 NSError
的 userInfo
:
RKObjectMapperErrorObjectsKey
RKObjectMapping *errorMapping = [RKObjectMapping mappingForClass:[RKErrorMessage class]];
[errorMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@"error" toKeyPath:@"errorMessage"]];
这导致了这个输出:
Error Domain=org.restkit.RestKit.ErrorDomain Code=1004 "<null>" UserInfo=0x7ff8abe678e0 {RKObjectMapperErrorObjectsKey=(
(null)
), NSLocalizedDescription=<null>}
现在我卡在了这一点上。我如何映射服务器错误响应的键,以便我可以访问 returned 的 code
以及作为两个单独值的 message
?
您可能已经正确映射了 TAG_RKErrorMessage 实例。您是否尝试从给定的 NSError 中提取它?您可以使用 RKObjectMapperErrorObjectsKey 作为 NSError 的 userInfo 字典上的键来获取所有映射错误消息的数组:
NSArray* objectMapperErrorObjectsArray = [error.userInfo objectForKey:RKObjectMapperErrorObjectsKey];
然后您可以遍历该数组以检查每个错误是否符合您要响应的条件,例如,如果您想要使用错误消息 "Invalid token" 响应 403 响应代码,您可以这样做:
NSArray* objectMapperErrorObjectsArray = [error.userInfo objectForKey:RKObjectMapperErrorObjectsKey];
for (RKErrorMessage* objectMapperErrorObject in objectMapperErrorObjectsArray)
{
if ([objectMapperErrorObject.errorMessage isEqual:@"Invalid token"])
{
if (operation.HTTPRequestOperation.response.statusCode == 403)
{
//Code to handle a 403 response status code when error message is "Invalid token".
}
}
}
提示:如果你想使用内置的RKErrorMessage
而不创建任何子类,你可以将所有错误JSON属性映射到RKErrorMessage.userInfo
这样:
Objective-C:
RKObjectMapping *errorMapping = [RKObjectMapping mappingForClass:[RKErrorMessage class]];
[errorMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:nil toKeyPath:@"userInfo"]];
RKResponseDescriptor *errorDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:errorMapping method:RKRequestMethodAny pathPattern:nil keyPath:"error" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassClientError)];
Swift:
let errorMapping = RKObjectMapping(forClass: RKErrorMessage.self);
errorMapping.addPropertyMapping(RKAttributeMapping(fromKeyPath: nil, toKeyPath: "userInfo"));
let errorResponseDescriptor = RKResponseDescriptor(
mapping: errorMapping,
method: RKRequestMethod.Any,
pathPattern: nil,
keyPath: "error",
statusCodes: RKStatusCodeIndexSetForClass(UInt(RKStatusCodeClassClientError)))
);