Steve Kanter
Steve Kanter

Reputation: 315

Restkit NSString includes metadata

I have a JSON file that i'm downloading from the web and parsing using RestKit. My problem is, I have a property with an array of strings that i'm trying to map into their own object. For some reason, when parsing that string, it ends up including the metadata object's description in the string. Please see my code snippets below for what i'm currently using, and the errors i'm experiencing. Note: I removed any core data integration and made my test as bare-bones as I could to attempt to track down the issue.

Object interfaces

@interface BLAuthor : NSObject

@property (nonatomic, retain) NSString *name;

@end

@interface BLVolume : NSObject

@property (nonatomic, retain) NSString *id;
@property (nonatomic, retain) NSSet *authors;
@end

Mapping and request operation

RKObjectMapping *volumeMapping = [RKObjectMapping mappingForClass:[BLVolume class]];
[volumeMapping addAttributeMappingsFromDictionary:@{ @"id": @"id" }];

RKObjectMapping *authorMapping = [RKObjectMapping mappingForClass:[BLAuthor class]];
[authorMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:nil
                                                                        toKeyPath:@"name"]];


[volumeMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"volumeInfo.authors"
                                                                              toKeyPath:@"authors"
                                                                            withMapping:authorMapping]];


NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful); 
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:volumeMapping
                                                                                   pathPattern:nil
                                                                                       keyPath:@"items"
                                                                                   statusCodes:statusCodes];

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"https://example.com/?q=123"]];

RKObjectRequestOperation *operation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:@[responseDescriptor]];
[operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *result) {
    NSLog(@"Success! %@", result);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
    NSLog(@"Failed with error: %@", [error localizedDescription]);
}];
NSOperationQueue *operationQueue = [NSOperationQueue new];
[operationQueue addOperation:operation];

JSON snippet

{
 "items": [
  {
   "id": "abc",
   "volumeInfo": {
    "authors": [
     "123"
    ]
  }
}

Resulting data - please note, everything after <BLAuthor = 0x08466250 | name = is actually part of the NSString property on BLAuthor:

Success! <RKMappingResult: 0x8468560, results={
    items =     (
        "<BLVolume = 0x08463F60 | id = mikPQFhIPogC | authors = {(
    <BLAuthor = 0x08466250 | name = 123 ({
    HTTP =     {
        request =         {
            URL = \"https://example.com/?q=123";
            headers =             {
            };
            method = GET;
        };
        response =         {
            URL = \"https://example.com/?q=123\";
            headers =             {
                \"Cache-Control\" = \"private, max-age=0, must-revalidate, no-transform\";
                \"Content-Type\" = \"application/json; charset=UTF-8\";
                Date = \"Sun, 23 Jun 2013 00:41:01 GMT\";
                Etag = \"\\\"I09ELXbrmOlE-RFCkDsRbIJj278/gPh8_OxpfA9YHXz_P_25F8A4orw\\\"\";
                Expires = \"Sun, 23 Jun 2013 00:41:01 GMT\";
                Server = GSE;
                \"Transfer-Encoding\" = Identity;
                \"X-Content-Type-Options\" = nosniff;
                \"X-Frame-Options\" = SAMEORIGIN;

Thanks in advance to anyone who can help me resolve this! I'm at wits end - tried to remove as many variables from my testing as I can, and have searched both the web and RestKit's source looking for the cause.

Upvotes: 1

Views: 402

Answers (2)

Steve Kanter
Steve Kanter

Reputation: 315

So, i've come to a sad conclusion - nothing is broken, my code works perfectly.

With relationships, apparently RestKit sets your objects to an NSProxy subclass. The subclass overrides -description and returns @"%@ (%@)", originalObject, metadata. So when logging the description of the object, I get that, instead of the ACTUAL objects' value. Very irritating and difficult to track down. I'm going to be opening an issue on RestKit to remove this confusing description, as when building my app without a UI yet, logging the description of the actual object is important.

Upvotes: 1

Gabriele Petronella
Gabriele Petronella

Reputation: 108101

The problem is with this mapping

[authorMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:nil
                                                                    toKeyPath:@"name"]];

You're basically saying: "map whatever you find onto the name property".

This can only work in case you're matching the path as opposed to the key in the response descriptor, as suggested here. But in order to do so, you would need the response to return the string array standalone, which is not your case.

As per the same post, you can try with

[authorMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:@""
                                                                    toKeyPath:@"name"]];

but I am skeptical it could work.

If you have control over the APIs, I'd suggest to change the format to a more RESTful one, by returning full-fledged resources instead of plain strings inside the array.

Upvotes: 1

Related Questions