Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 781
Diego Barros Avatar asked Aug 16 '13 03:08

Diego Barros


2 Answers

You can convert the source object into a dictionary and send that instead. Then the response data will naturally be mapped into a dictionary. This should be a minimal change to your mappings and a small change to the other code (using KVC dictionaryWithValuesForKeys:).

like image 38
Wain Avatar answered Oct 04 '22 20:10

Wain


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);
                       }];
like image 94
Jonukas Avatar answered Oct 04 '22 19:10

Jonukas