iosobjective-crestkitrestkit-0.20

Handle a POST response with RestKit that is not mapped to the POST object


I have a situation where I am doing a post of an object (not a managed one, just an NSObject derived one), but the response from the REST API is not a JSON representation of the kind of object being posted. It is something else altogether. Is it possible to handle this?

Say I post an object (JSON):

{
  "prop1" : 123,
  "prop2" : 5
}

And the response if not an object with properties prop1 and prop2, as RestKit expects by default, but something else:

{
  "data" : [1,2,3,4,5,6],
  "message" : "hello world"
}

I've seen examples where operation.targetObject was set to nil, but (I believe) this is only in Core Data managed scenarios.

I am trying something simple like this:

RKObjectRequestOperation *operation = [self.objectManager appropriateObjectRequestOperationWithObject:body method:RKRequestMethodPOST path:@"items" parameters:nil];

[operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *result) {
   // success is called, but the result does not contain what the response JSON is
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
  // failure
}];

[operation setWillMapDeserializedResponseBlock:^id(id deserializedResponseBody) {
    // deserializedResponseBody is always nil
}];

[operation start];

I thought I could be able to look at the response contents in the setWillMapDeserializedResponseBlock, but it is always nil.

Because the posted object has prop1 and prop2 properties, and how RestKit works by default, it expects JSON with said properties. But, since the result has nothing to do with the posted object, prop1 and prop2 are just nil (which I don't care for anyway).

By the way, I have setup the request mapping correctly, so the body being passes in the operation object is correctly mapping my NSObject and sending it in the correct JSON format to the server.

Is there a way that I can make such a call with RestKit, and manually pull out what I am looking for on the success event? Even if it was a dictionary representation of the JSON response?


Solution

  • I'd just create a new object for your response and map your response to that.

    Objects

    @interface MYRequest : NSObject
    
    @property NSNumber *prop1;
    @property NSNumber *prop2;
    
    @end
    
    @interface MYResponse : NSObject
    
    @property NSArray *data;
    @property NSString *message;
    
    @end
    

    Mappings

    RKObjectMapping *requestMapping = [RKObjectMapping requestMapping];
    [requestMapping addAttributeMappingsFromArray:@[@"prop1", @"prop2"]];
    
    RKObjectMapping *responseMapping = [RKObjectMapping mappingForClass:[MYResponse class]];
    [requestMapping addAttributeMappingsFromArray:@[@"data", @"message"]];
    

    Descriptors

    RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:requestMapping
                                                                                   objectClass:[MYRequest class]
                                                                                   rootKeyPath:nil
                                                                                        method:RKRequestMethodPOST];
    
    RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:responseMapping
                                                                                            method:RKRequestMethodPOST
                                                                                       pathPattern:@"items"
                                                                                           keyPath:nil
                                                                                       statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
    

    Object Manager

    [self.objectManager addRequestDescriptor:requestDescriptor];
    [self.objectManager addResponseDescriptor:responseDescriptor];
    

    Execute

    MYRequest *body = [MYRequest new];
    [body setProp1:@123];
    [body setProp2:@5];
    
    [self.objectManager postObject:body
                              path:@"items"
                        parameters:nil
                           success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
                               MYResponse *result = [mappingResult firstObject];
                               NSLog(@"Data: %@\nMessage: %@", [result data], [result message]);
                           }
                           failure:^(RKObjectRequestOperation *operation, NSError *error) {
                               NSLog(@"Error: %@", error);
                           }];