Как сопоставить RKResponse RKClient с RKObjectMapping

Я делаю многостраничную публикацию данных изображения и некоторых значений, используя RKClient RestKit, например:

RKParams* params = [RKParams params];
[params setValue:foo.accountId forParam:@"accountId"];
[params setValue:foo.identifier forParam:@"fooId"];
[params setValue:_photoId forParam:@"photoId"];
[params setData:data MIMEType:@"image/png" forParam:@"image"];
[[RKClient sharedClient] post:@"/foo/uploadPhoto" params:params delegate:self];

Это прекрасно работает, и мой внутренний сервер отвечает JSON-представлением объекта модели на стороне сервера, это выглядит так:

{"id":"4ee2b4670364720c089e75b9","accountId":"4ebee3469ae2d8adf983c561","fooId":"4ec0983d036463d900841f0b","photoId":"E5B20AF1-9F10-4175-8262-852BDA3DEDE9","filename":"4ebee3469ae2d8adf983c561_4ec0983d036463d900841f0b_E5B20AF1-9F10-4175-8262-852BDA3DEDE9","contentType":"image/png"}

Теперь мне нужно сопоставить это с объектом модели на стороне клиента (iOS). Объект модели на стороне клиента почти такой же, но не идентичен (поэтому использование метода RKJSONParser objectFromString не вариант), поэтому у меня есть определенный RKObjectMapping, который обрабатывает сопоставление. Делегат RKClient получает только RKResponse, так как я могу использовать ответ вместе с картографом, чтобы получить экземпляр моего объекта модели на стороне клиента?

Примечание. Чтобы было ясно, я очень хорошо знаком с тем, как это работает при использовании RKObjectManager для публикации объекта и сопоставления ответа. Уникальная часть моей ситуации заключается в том, что я использую RKClient для создания поста, состоящего из нескольких частей. К сожалению, RKClient, похоже, не имеет простых методов для обработки сопоставления ответов, как это делает RKObjectManager ... если только я что-то не упустил (на что я надеюсь и что вы все мне укажете;).


person Michael Peterson    schedule 10.12.2011    source источник


Ответы (1)


Итак, этот пост был похож (но нефункционален), и он дал мне некоторые идеи о новой технике использования этого метода на RKObjectLoader

- (RKObjectLoader *)postObject:(id<NSObject>)object delegate:(id<RKObjectLoaderDelegate>)delegate block:(void ( ^ ) ( RKObjectLoader *))block

Так что теперь я мог получить преимущество от сопоставления, которое не было очевидным, как использовать RKClient.

Настройка маршрутизатора:

RKObjectManager *objectManager = [RKObjectManager objectManagerWithBaseURL:kApiUrlBase];
[objectManager.router routeClass:[PAPetPhoto class] toResourcePath:@"/pet/uploadPhoto" forMethod:RKRequestMethodPOST];

Настройка сопоставления:

RKObjectMapping *papetPhotoMapping = [RKObjectMapping mappingForClass:[PAPetPhoto class]];
[papetPhotoMapping mapKeyPath:@"id" toAttribute:@"identifier"];
[papetPhotoMapping mapAttributes:@"accountId", @"petId", @"photoId", @"filename", @"contentType", nil];
[objectManager.mappingProvider addObjectMapping:papetPhotoMapping];
[objectManager.mappingProvider setSerializationMapping:[papetPhotoMapping inverseMapping] forClass:[PAPetPhoto class]];
[objectManager.mappingProvider setMapping:papetPhotoMapping forKeyPath:@"petPhoto"];

Пост: (обратите внимание, поскольку я создал все свои параметры в блоке, мой объект является просто фиктивным экземпляром для запуска правильной маршрутизации и сопоставления).

    PAPetPhoto *photo = [[PAPetPhoto alloc] init];
    [[RKObjectManager sharedManager] postObject:photo delegate:self block:^(RKObjectLoader *loader){

        RKParams* params = [RKParams params];
        [params setValue:pet.accountId forParam:@"accountId"];
        [params setValue:pet.identifier forParam:@"petId"];
        [params setValue:_photoId forParam:@"photoId"];
        [params setValue:_isThumb ? @"THUMB" : @"FULL" forParam:@"photoSize"];
        [params setData:data MIMEType:@"image/png" forParam:@"image"];

        loader.params = params;
    }];

Конечная точка сервера (Java, Spring MVC)

    @RequestMapping(value = "/uploadPhoto", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, Object> handleFormUpload(@RequestParam("accountId") String accountId,
                                    @RequestParam("petId") String petId,
                                    @RequestParam("photoId") String photoId,
                                    @RequestParam("photoSize") PhotoSizeEnum photoSize,
                                    @RequestParam("image") Part image) throws IOException {

        if (log.isTraceEnabled()) 
            log.trace("uploadPhoto. accountId=" + accountId + " petId=" + petId + " photoId=" + photoId + " photoSize=" + photoSize);

        PetPhoto petPhoto = petDao.savePetPhoto(accountId, petId, photoId, photoSize, image);

        Map<String, Object> map = GsonUtils.wrapWithKeypath(petPhoto, "petPhoto");
        return map;
    }

Ответ сервера в формате JSON (обратите внимание на keyPath "petPhoto", который соответствует настройке сопоставления):

{
    petPhoto =     {
        accountId = 4ebee3469ae2d8adf983c561;
        contentType = "image/png";
        filename = "4ebee3469ae2d8adf983c561_4ec0983d036463d900841f09_3FED4959-1042-4D8B-91A8-76AA873851A3";
        id = 4ee2e80203646ecd096d5201;
        petId = 4ec0983d036463d900841f09;
        photoId = "3FED4959-1042-4D8B-91A8-76AA873851A3";
    };
}

Делегировать:

- (void) objectLoader:(RKObjectLoader*)objectLoader didLoadObject:(id)object {

    if ([objectLoader wasSentToResourcePath:@"/pet/uploadPhoto"]) {
       PAPetPhoto *photo = (PAPetPhoto*)object;
    }
}
person Michael Peterson    schedule 12.12.2011
comment
Я попробовал это на своей странице входа и дошел до того, что он отправляет запрос на указанный маршрут. Но логин всегда терпит неудачу, даже если я ввожу правильные параметры (адрес электронной почты и пароль). Я подозреваю, что настройка параметров не прошла, но я не уверен, в чем причина. Он отлично работает, если я использую метод RKClient post:params:. :( - person Hlung; 21.03.2012