Michael Bethke
Michael Bethke

Reputation: 180

Mapping nested objects and arrays

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

Upvotes: 0

Views: 357

Answers (2)

Amin Negm-Awad
Amin Negm-Awad

Reputation: 16660

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

Upvotes: 1

Gal
Gal

Reputation: 381

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

Upvotes: 1

Related Questions