0
votes

How do I gracefully handle an (expected) nil keypath during a RestKit GET?

When I make a getAllEvents API call if the user doesn't have any events the API will return a null value in the payload, e.g. {"events":null}. The null value causes the RestKit request: didFailLoadWithError and objectLoader: didFailWithError methods to be invoked, which I don't necessarily want because this is the expected behavior where there are 0 events. The error message it gives is Could not find an object mapping for keyPath: ''.

Can I handle this in the mapping config and/or the delegate methods, or do I need to modify the API, perhaps to return an empty string instead of null. Is there a standard for what JSON should return when the list is empty?

2

2 Answers

2
votes

Is there a standard for what JSON should return when the list is empty?

I don't know actualy, but I'd go with an empty array:

{ 'events' : [] }

If a value is null, I'd just not send it at all [saving bandwidth].

EDIT: see this answer too.

1
votes

UPDATE: This no longer works beyond RestKit v0.10.x. See @moonwave99's answer.

Found a solution!

I ended up doing something very similar to moonwave's suggestion, except that I'm now changing the null object to an empty array.

- (void)objectLoader:(RKObjectLoader*)loader willMapData:(inout id *)mappableData {

  id events = [*mappableData objectForKey:@"events"];

  if (events == [NSNull null]) {
    NSLog(@"it's null");
    [*mappableData setObject:@"" forKey:@"events"];
  }
}

To successfully handle the now empty, not null array I had to tell the events mapping to ignore unknown key paths.

[eventsMapping setIgnoreUnknownKeyPaths:YES];

Now, instead of invoking the didFailWithError delegate method, RestKit invokes didLoadObjects like I'd expected/hoped all along. From there I'm able to check if the array is empty before trying to assign to my native Cocoa object.

- (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects {

  if ([objects count] == 0) {

    // No events, alert user

  }
  else if ([[objects objectAtIndex:0] isKindOfClass:[Events class]]) {

    Events *events = [objects objectAtIndex:0];

}