0

Good afternoon, everyone!

I'm trying to figure out how to map objects with nested arrays, but my project keeps being terminated due to an uncaught exception. I assume I'm not mapping something correctly, but I'm being told something isn't key-value coding compliant.

How do I map an object with a nested array?

Following is the footprint of the JSON I'm trying to map, the interface and implementation, and the error that's being throw, respectively. Finally, there is a link to my project on GitHub, incase I've left anything out, or seeing the full source would be helpful.

JSON

{
  "href": "string",
  "items": [
    {
      "type": "string",
      "status": "string",
      "name": "string",
      "publisher": "string",
      "publisherId": "string",
      "description": "string",
      "url": "string",
      "smallLogoImageUrl": "string",
      "tileImageUrl": "string",
      "heroImageUrl": "string",
      "tags": [
        "string",
        "string"
      ],
      "createdOn": "2015-04-22T18:55:40.782Z",
      "downloadUrl": "string",
      "getProductCodeUrl": "string",
      "metadata": {
        "exeType": "string",
        "packageFileName": "string",
        "installDirectory": "string",
        "executableName": "string"
      },
      "id": "string"
    }
  ]
}

Interface (.h)

@interface SFrontPageItem : NSObject

@property (nonatomic, strong) NSString *type;
@property (nonatomic, strong) NSString *status;
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *publisher;
@property (nonatomic, strong) NSString *publisherId;
@property (nonatomic, strong) NSString *productDescription;
@property (nonatomic, strong) NSString *url;
@property (nonatomic, strong) NSString *smallLogoImageUrl;
@property (nonatomic, strong) NSString *tileImageUrl;
@property (nonatomic, strong) NSString *heroImageUrl;
@property (nonatomic, strong) NSArray *tags;
@property (nonatomic, strong) NSString *createdOn;
@property (nonatomic, strong) NSString *downloadUrl;
@property (nonatomic, strong) NSString *getProductCodeUrl;
@property (nonatomic, strong) NSArray *metadata;
@property (nonatomic, strong) NSString *productID;

@end


@interface SFrontPage : NSObject

@property (nonatomic, strong) NSString *href;
@property (nonatomic, strong) NSArray *items;

@end

Implementation (.m)

- (void) getFrontPage
{

    AppDelegate *appDelegate = [[NSApplication sharedApplication] delegate];

    RKObjectMapping *itemMapping = [RKObjectMapping mappingForClass:[SFrontPageItem class]];

    [itemMapping addAttributeMappingsFromDictionary:@{
                                                        @"type": @"type",
                                                        @"status": @"status",
                                                        @"name": @"name",
                                                        @"publisher": @"publisher",
                                                        //@"publisherId": @"publisherId",
                                                        @"description": @"description",
                                                        @"url": @"url",
                                                        //@"smallLogoImageUrl": @"smallLogoImageUrl",
                                                        @"tileImageUrl": @"tileImageUrl",
                                                        //@"heroImageUrl": @"heroImageUrl",
                                                        //@"tags": @"tags",
                                                        @"createdOn": @"createdOn",
                                                        //@"downloadUrl": @"downloadUrl",
                                                        //@"getProductCodeUrl": @"getProductCodeUrl",
                                                        //@"metadata": @"metadata",
                                                        @"id": @"productID"
                                                    }];
    //itemMapping.forceCollectionMapping = YES;


    RKObjectMapping *frontpageMapping = [RKObjectMapping mappingForClass:[SFrontPage class]];
    [frontpageMapping addAttributeMappingsFromDictionary:@{
                                                           @"href": @"href"
                                                        }];


    [frontpageMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"items"
                                                                                     toKeyPath:@"items"
                                                                                   withMapping:itemMapping]];


    RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:frontpageMapping
                                                                                            method:RKRequestMethodGET
                                                                                       pathPattern:nil
                                                                                           keyPath:nil
                                                                                       statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];

    [self.objectManager.HTTPClient setAuthorizationHeaderWithUsername:self.sconnection.apiKey.key password:self.sconnection.apiKey.secret];
    [self.objectManager addResponseDescriptor:responseDescriptor];
    [self.objectManager getObjectsAtPath:@"/api/frontpage/rest" parameters:nil
        success:^(RKObjectRequestOperation *operation, RKMappingResult *result)
        {

            SFrontPage *newFrontpage = result.firstObject;
            NSLog (@"   HREF: %@", newFrontpage.href);

            //NSLog (@"ITEMS: %@", newFrontpage.items.firstObject);
            //SFrontPageItem *newFrontpageItem = newFrontpage.items.firstObject;
            //NSLog (@"Unexpected Great Thing %@", newFrontpageItem );

            [appDelegate.loginViewController apiConnectionSuccess];


        } failure:^(RKObjectRequestOperation *operation, NSError *error)
        {

            [appDelegate.loginViewController updateLoginWindowHeaderLabelTo:@"Unable to Load Frontpage"];
            [appDelegate.loginViewController apiConnectionFailure];
        }];
}

Error

[<SFrontPageItem 0x6180001026d0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key description.

Source

The full source can be found on GitHub, with the relevant files being APIManager.h & APIManager.m.

I hope I've been clear enough, I sometimes miss the mark when forming a question about something I don't completely understand. I'm new to both ObjC, and RestKit, so I'm sure there are already a lot of confusing things in my code. Thanks for taking the time to read through it, and consider my question. If I can clarify anything, please let me know!

Michael

2 Answers 2

1

You map from description to description, but the property has the identifier productDescription. Change the mapping or the property name.

Sign up to request clarification or add additional context in comments.

2 Comments

I didn't catch that, thank you! I'm a little dumbfounded that this was the whole problem. Goes to show how important double checking these things is. I'll accept your answer as soon as it lets me.
On these errors one can spend his life time. I got it from the error message that says, that it cannot find description. Well, me, too. ;-)
1

Try use some ready solutions. https://github.com/aryaxt/OCMapper https://github.com/isair/JSONHelper

1 Comment

Thank you for the suggestion, @Gal ! RestKit seems to be made for object mapping, and I'd like to avoid using too many third-party extensions. If possible, I would prefer finding a solution for RestKit, but if I can't get anything to work, I'll consider the projects you've mentioned. Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.