2

因此,我使用的是 RestKit 0.20 版,并且我成功地以 JSON 格式发送了一个 POST 请求。我的服务器后端(Java REST WS (Jersey))正在正确映射所有内容,Restkit 也是如此。

我现在的问题是我发送了一个不同的对象,因为我有 Post。我在 RestKit 中有以下映射设置:

- (void)createUserAccount:(DeviceDTO *)devDTO :(UserDTO *)userDTO block:(void (^)(id))block{
    id errorCode __block;
    // Configure a request mapping for our Article class. We want to send back title, body, and publicationDate
    RKObjectMapping* deviceRequestMapping = [RKObjectMapping requestMapping];
    [deviceRequestMapping addAttributeMappingsFromArray:@[ @"model", @"name", @"systemName", @"systemVersion", @"devToken" ]];

    RKObjectMapping* msRequestMapping = [RKObjectMapping requestMapping];
    [msRequestMapping addAttributeMappingsFromArray:@[ @"validSince", @"validTill" ]];

    RKObjectMapping* countryRequestMapping = [RKObjectMapping requestMapping];
    [countryRequestMapping addAttributeMappingsFromArray:@[ @"idNumberDTO", @"iso2DTO", @"short_nameDTO", @"calling_codeDTO" ]];

    RKObjectMapping* contactsRequestMapping = [RKObjectMapping requestMapping];
    [contactsRequestMapping addAttributeMappingsFromArray:@[ @"fullName", @"phoneNumber"]];

    RKObjectMapping* userRequestMapping = [RKObjectMapping requestMapping];
    [userRequestMapping addAttributeMappingsFromArray:@[ @"displayName", @"phoneNumber", @"status", @"userID", @"realName" ]];

    [userRequestMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"deviceInfo" toKeyPath:@"device" withMapping:deviceRequestMapping]];
    [userRequestMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"memberShipDetails" toKeyPath:@"memberShip" withMapping:msRequestMapping]];
    [userRequestMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"country" toKeyPath:@"country" withMapping:countryRequestMapping]];
    [userRequestMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"contacts" toKeyPath:@"contacts" withMapping:contactsRequestMapping]];

    RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:userRequestMapping objectClass:[UserDTO class] rootKeyPath:nil];


    //Create Objects
    UserDTO *user = [[UserDTO alloc]init];
    ..........

    DeviceDTO *device = [[DeviceDTO alloc]init];
    ..........

    user.deviceInfo = device;

    MemberShipDTO *ms = [[MemberShipDTO alloc]init];
    .......

    user.memberShipDetails = ms;



    RKObjectMapping *errorMapping = [RKObjectMapping mappingForClass:[ErrorMapping class]];
    [errorMapping addAttributeMappingsFromArray:@[ @"errorCode", @"errorMessage" ]];

    RKObjectMapping* deviceRespMapping = [RKObjectMapping mappingForClass:[DeviceDTO class]];
    [deviceRespMapping addAttributeMappingsFromArray:@[ @"model", @"name", @"systemName", @"systemVersion", @"devToken" ]];

    RKObjectMapping* msRespMapping = [RKObjectMapping mappingForClass:[MemberShipDTO class]];
    [msRespMapping addAttributeMappingsFromArray:@[ @"validSince", @"validTill" ]];

    RKObjectMapping* contactsRespMapping = [RKObjectMapping mappingForClass:[ContactDTO class]];
    [contactsRespMapping addAttributeMappingsFromArray:@[ @"fullName", @"phoneNumber"]];

    RKObjectMapping* userRespMapping = [RKObjectMapping mappingForClass:[UserDTO class]];
    [userRespMapping addAttributeMappingsFromArray:@[ @"displayName", @"phoneNumber", @"status", @"userID", @"realName" ]];

    [userRespMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"deviceInfo" toKeyPath:@"device" withMapping:deviceRespMapping]];
    [userRespMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"memberShipDetails" toKeyPath:@"memberShip" withMapping:msRespMapping]];
    [userRespMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"country" toKeyPath:@"country" withMapping:countryRequestMapping]];
    [userRespMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"contacts" toKeyPath:@"contacts" withMapping:contactsRespMapping]];

    [errorMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"user" toKeyPath:@"user" withMapping:userRespMapping]];

    RKResponseDescriptor *errorDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:errorMapping pathPattern:nil keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];

    [RKMIMETypeSerialization registerClass:[RKNSJSONSerialization class] forMIMEType:@"application/json"];

    [[RKObjectManager sharedManager] setRequestSerializationMIMEType:RKMIMETypeJSON];
    [[RKObjectManager sharedManager] setAcceptHeaderWithMIMEType:RKMIMETypeJSON];
    [[RKObjectManager sharedManager] addRequestDescriptor:requestDescriptor];
    [[RKObjectManager sharedManager] addResponseDescriptor:errorDescriptor];
    [[RKObjectManager sharedManager] postObject:user path:@"user/integrate" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult){
        NSArray* statuses = [mappingResult array];
        NSLog(@"Loaded statuses: %@", statuses);
        errorCode = [statuses objectAtIndex:0];
        NSLog(@"errorCode == %@", errorCode);
        block(errorCode);
        RKLogInfo(@"Load collection of Articles: %@", mappingResult.array);
    }failure:^(RKObjectRequestOperation *operation, NSError *error) {
        block(nil);
        RKLogError(@"Operation failed with error: %@", error);
    }];

}

我请求的 JSON 很好,响应也很好:

{
    "errorMessage": null,
    "errorCode": 190,
    "user": {
        "displayName": "Saif",
        "phoneNumber": "+xxx",
        "userID": "xxx",
        "country": {
            "idNumberDTO": 83,
            "short_nameDTO": "Germany",
            "calling_codeDTO": "+49",
            "iso2DTO": "DE"
        },
        "device": {
            "devToken": "xxx",
            "model": "iPhone",
            "name": "Saifs iPhone",
            "systemName": "iPhone OS",
            "systemVersion": "6.1.4",
            "id": null
        },
        "memberShip": {
            "validSince": 1376047810000,
            "validTill": 1407583810000,
            "id": null
        },
        "contacts": [
            {
                "fullName": "xxx",
                "phoneNumber": "xxx"
            },
            {
                "fullName": "xxx",
                "phoneNumber": "xxx"
            },
            ....,
            ....,
            ....
        ],
        "id": null
    }
}

在我的 RK 方法上,我得到了这条线:

    errorCode = [statuses objectAtIndex:0];

这个错误:

2013-08-09 13:30:12.246 xxx![19310:440f] W restkit.object_mapping:RKMapperOperation.m:99 Adding mapping error: Expected an object mapping for class of type 'UserDTO', provider returned one for 'ErrorMapping'
2013-08-09 13:30:12.247 xxx![19310:440f] I restkit.network:RKObjectRequestOperation.m:250 POST 'http://192.168.2.115:8080/WAZZUUPWS/rest/service/user/integrate' (200 OK / 0 objects) [request=1.3406s mapping=0.0047s total=1.3461s]
2013-08-09 13:30:12.249 xxx![19310:907] Loaded statuses: (
)
2013-08-09 13:30:12.250 xxx![19310:907] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array'

看起来无法映射响应,这就是 Resultarray 为空的原因。知道如何从响应中映射复杂对象吗?

4

1 回答 1

9

Restkit 文档

默认情况下,当使用 postObject 或 putObject 时,RestKit 会自动尝试将 JSON 结果映射到发布的 sourceObject 中。

在您的代码中,您发布了一个 UserDTO 实例并接收一个应该映射到 ErrorMapping 的 JSON 响应。因此,您会从 Restkit 获得 RKMappingErrorTypeMismatch。

文档中所述,您可以自己创建一个 RKRequestOperation 并将目标对象设为 nil 以覆盖默认值,而不是使用 post。

RKObjectRequestOperation *operation = [[RKObjectManager sharedManager] appropriateObjectRequestOperationWithObject:user
                                                                                                            method:RKRequestMethodPOST
                                                                                                              path:@"user/integrate"
                                                                                                        parameters:nil];
operation.targetObject = nil;

[operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
    DLog(@"integrated user: %@", mappingResult.firstObject);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
    DLog(@"error integrating user: %@", user);
}];

但是,如果您可以修改后端,我更愿意更改返回的 JSON。不要在 JSON 响应中包含错误代码,而是使用相关 (HTTP) 响应状态代码并在您的响应中仅包含特定于域模型的实体。

于 2013-08-09T14:36:17.030 回答