Rizon
Rizon

Reputation: 1546

Restkit simple NSDictionary mapping

Seems like a really easy task, but I find myself struggling.. I have this JSON response:

{"data":
    {"badParams":
        {"arbitraryKey":"arbitraryValue",
        "arbitraryKey2":"arbitraryValue2",
        "arbitraryKey3":"arbitraryValue3" ,
        ...
        }
    }
}

I'd like to parse that response to NSDictionary, containing all the key:value pairs I got in the response:

NSDictionary *response == {"arbitraryKey":"arbitraryValue",
            "arbitraryKey2":"arbitraryValue2",
            "arbitraryKey3":"arbitraryValue3",...} 

I tried RKDynamicMapping but couldn't make it :\

Any advise?

Upvotes: 2

Views: 3263

Answers (3)

Kyle Clegg
Kyle Clegg

Reputation: 39480

If your target object is an NSDictionary, then you might be better suited to use NSJSONSerialization than RestKit. With RestKit you really don't parse JSON into dictionaries, but rather into native objective-c objects, i.e. your data models.

For more on setting up your own objects, relational mappings, and configuring the RestKit objectManager you should check out the RestKit Object Mapping Guide; they have some really solid examples on how that can be done.

UPDATE:

For a simple JSON -> NSDictionary mapping that does not require any authentication I would simply use this:

NSString *urlString = @"http://www.yourserver.com/api";
NSData *data = [NSData dataWithContentsOfURL:urlString];
NSError *error = nil;
NSDictionary *parsedData = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];

Upvotes: 3

Songlin
Songlin

Reputation: 372

To summarize @Xean 's solution, here is the working code snippet.

RKObjectMapping *dictionaryMapping = [RKObjectMapping mappingForClass:[RestKitDictionaryContainer class]];
[dictionaryMapping addAttributeMappingsFromArray:@[@"arbitraryKey", @"arbitraryKey2", @"arbitraryKey3"]];

then create response descriptor:

RKResponseDescriptor *responseDescriptor =
[RKResponseDescriptor responseDescriptorWithMapping:dictionaryMapping
                                             method:RKRequestMethodAny
                                        pathPattern:@"/your/api"
                                            keyPath:@"data.badParams"
                                        statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];

finally the request operation part

RKObjectRequestOperation *objectRequestOperation = [[RKObjectRequestOperation alloc] initWithRequest:request responseDescriptors:@[responseDescriptor]];
[objectRequestOperation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
    NSString *value = [((RestKitDictionaryContainer *)[[mappingResult dictionary] objectForKey:@"content"]).dictionary objectForKey:@"arbitraryKey"];
            //....
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
    RKLogError(@"Operation failed with error: %@", error);
}];
[objectRequestOperation start];

Upvotes: 3

Obenland
Obenland

Reputation: 866

RestKit is not be prepared for NSDictionarys. But you could do a bit ugly workaround if it is necessary...

This class wraps a dictionary in a container class thats forwarding the KVC calls to the setObject:forKey of the dictionary.

@interface RestKitDictionaryContainer : NSObject
@property (nonatomic, strong) NSMutableDictionary * dictionary;
@end

@implementation RestKitDictionaryContainer

- (id)init
{
    self = [super init];
    if (self) {
        _dictionary = [NSMutableDictionary dictionary];
    }
    return self;
}

-(void)setValue:(id)value forUndefinedKey:(NSString *)key
{
    [_dictionary setObject:value forKey:key];
}

-(id)valueForUndefinedKey:(NSString *)key {
    return [_dictionary objectForKey:key];
}
@end

Now you have to do all mappings as usual. After a RestKit call you only have to get the dictionary out of this class or use it as a dictionary. Well, I think this is pretty ugly and should not be used but it is your decision...

Upvotes: 5

Related Questions