如何在Restkit中映射自定义错误键?

时间:2015-01-08 18:16:17

标签: ios objective-c restkit restkit-0.20

当用户在我们的服务器上成功注册时,它会响应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返回错误时,我会收到消息以及代码。这些是我尝试这样做的方式:

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

这个显然只会使用此输出返回错误的消息部分:

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}

最后我尝试使用此映射至少尝试将字典显示为RKObjectMapperErrorObjectsKey NSError userInfo的{​​{1}}:

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>}

现在我陷入了困境。如何映射服务器错误响应的键,以便我可以访问返回的code以及message作为两个单独的值?

2 个答案:

答案 0 :(得分:3)

您可能正确映射了TAG_RKErrorMessage实例。您是否尝试从已经给出的NSError中提取它?您可以使用RKObjectMapperErrorObjectsKey作为NSError的userInfo字典上的键来获取所有映射错误消息的数组:

NSArray* objectMapperErrorObjectsArray = [error.userInfo objectForKey:RKObjectMapperErrorObjectsKey];

然后,您可以遍历该数组以检查每个错误以查找您要响应的条件,例如,如果您想响应403响应代码并显示错误消息“Invalid token”,您可以这样做:

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".
        }
    }
}

答案 1 :(得分:1)

只是一个提示:如果您想在不创建任何子类的情况下使用内置RKErrorMessage,则可以通过以下方式将所有错误JSON属性映射到RKErrorMessage.userInfo

<强>目标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)];

<强>夫特

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