0
votes

I am having difficulty mapping a object in Restkit which is nested. The response is as follows:

{
  "status": "SUCCESS",
  "message": "Newsfeeds loaded successfully",
  "links": {
    "self": ""
  },
  "newsfeeds": [
    {
      "type": "post",
      "content": {
        "id": "39ff4ea6-71d4-4d9c-872b-94d878ec54fd",
        "owner_id": "75c72102-d7dc-44c6-bb62-c48b487897c4",
        "owner_firstname": "Goran",
        "owner_lastname": "Don",
        "owner_profilephoto": "88f5930b-e779-47ac-86b7-4f31cd0d82aa.jpg",
        "contents": [
          {
            "type": "text",
            "content": "Being the richest man in the cemetery doesn't matter to me. Going to bed at night saying we've done something wonderful, that's what matters to me.\n        Sometimes when you innovate, you make mistakes. It is best to admit them quickly, and get on with improving your other innovations"
          },
          {
            "type": "url",
            "content": {
              "title": "Beautiful landscape view     Of New Zealand and Australia is available here",
              "position": "landscape",
              "url": "39ff4ea6-71d4-4d9c-872b-94d878ec54fd/Img_62151fbd-119f-4a84-91a9-f37bfa6293db.jpg"
            }
          }
        ],
        "postdatetime": "May 18 2016 12:18:54.442 UTC",
        "selfLike": false,
        "likes": 0,
        "comments": 0,
        "starred": "false"
      }
    },
    {
      "type": "post",
      "content": {
        "id": "7117d132-1811-4ac7-bfaf-bbb397eefb10",
        "owner_id": "75c72102-d7dc-44c6-bb62-c48b487897c4",
        "owner_firstname": "Goran",
        "owner_lastname": "Don",
        "owner_profilephoto": "88f5930b-e779-47ac-86b7-4f31cd0d82aa.jpg",
        "contents": [
          {
            "type": "text",
            "content": "Hi this is a test"
          }
        ],
        "postdatetime": "May 18 2016 11:42:24.978 UTC",
        "selfLike": false,
        "likes": 0,
        "comments": 0,
        "starred": "false"
      }
    },
    {
      "type": "post",
      "content": {
        "id": "fbeb20cf-c87b-40db-9753-9fa32aac921a",
        "owner_id": "75c72102-d7dc-44c6-bb62-c48b487897c4",
        "owner_firstname": "Goran",
        "owner_lastname": "Don",
        "owner_profilephoto": "88f5930b-e779-47ac-86b7-4f31cd0d82aa.jpg",
        "contents": [
          {
            "type": "url",
            "content": {
              "title": "",
              "position": "potrait",
              "url": "fbeb20cf-c87b-40db-9753-9fa32aac921a/Img_23771f1c-bb22-4335-ae3f-4e83d97c5c3c.jpg"
            }
          },
          {
            "type": "url",
            "content": {
              "title": "",
              "position": "landscape",
              "url": "fbeb20cf-c87b-40db-9753-9fa32aac921a/Img_a77e8349-b531-4d9d-944e-88971298c6fa.jpg"
            }
          }
        ],
        "postdatetime": "May 18 2016 07:39:07.937 UTC",
        "selfLike": true,
        "likes": 1,
        "comments": 0,
        "starred": "false"
      }
    },
    {
      "type": "post",
      "content": {
        "id": "71e005a1-71ec-4131-8131-bfd38337ec6a",
        "owner_id": "75c72102-d7dc-44c6-bb62-c48b487897c4",
        "owner_firstname": "Goran",
        "owner_lastname": "Don",
        "owner_profilephoto": "88f5930b-e779-47ac-86b7-4f31cd0d82aa.jpg",
        "contents": [
          {
            "type": "url",
            "content": {
              "title": "",
              "position": "potrait",
              "url": "post/71e005a1-71ec-4131-8131-bfd38337ec6a/Img_600f6fd0-14f9-4bf3-af6e-f36b7ffedbc6.jpg"
            }
          }
        ],
        "postdatetime": "May 18 2016 07:27:53.278 UTC",
        "selfLike": false,
        "likes": 0,
        "comments": 0,
        "starred": "false"
      }
    }
  ]
}

From the above, need to reach "content" within "contents" array. "content" sometimes return string and sometimes dictionary. I am trying to map as follows:

    RKObjectMapping * newsFeedMappingObject = [RKObjectMapping  mappingForClass:[NewsFeed class]];

[newsFeedMappingObject addAttributeMappingsFromDictionary:@{@"type" : @"type",}];

RKObjectMapping * responseMappingObject = [RKObjectMapping  mappingForClass:[ResponseMessage class]];

[responseMappingObject addAttributeMappingsFromDictionary:@{uStatus: @"status",uMessage: @"message",}];
[responseMappingObject addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"newsfeeds"
                                                                                   toKeyPath:@"newsfeeds"
                                                                                 withMapping:newsFeedMappingObject]];

RKObjectMapping * contentMappingObject = [RKObjectMapping  mappingForClass:[Content class]];

[contentMappingObject addAttributeMappingsFromDictionary:@{@"id": @"contentId"}];

[newsFeedMappingObject addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"content"
                                                                                      toKeyPath:@"cont"
                                                                                    withMapping:contentMappingObject]];

RKObjectMapping * postContentMappingObject = [RKObjectMapping  mappingForClass:[PostContent class]];

[postContentMappingObject addAttributeMappingsFromDictionary:@{@"type": @"type",}];

[contentMappingObject addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"contents"
                                                                                     toKeyPath:@"contents"
                                                                                   withMapping:postContentMappingObject]];

RKObjectMapping * postMappingObject = [RKObjectMapping  mappingForClass:[Post class]];

[postMappingObject addAttributeMappingsFromDictionary:@{@"title":@"title"}];

[postContentMappingObject addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"content"
                                                                                     toKeyPath:@"post"
                                                                                   withMapping:postMappingObject]];

When I run it the app crashes with log as:** * Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<__NSCFString 0x7fa302826d30> valueForUndefinedKey:]: this class is not key value coding-compliant for the key title.'

Trying my hands on dynamic mapping. But I think I'm doing it wrong:

 RKObjectMapping * newsFeedMappingObject = [RKObjectMapping  mappingForClass:[NewsFeed class]];
    [newsFeedMappingObject addAttributeMappingsFromDictionary:@{
                                                                @"type" : @"type",
                                                            }];

    RKObjectMapping * responseMappingObject = [RKObjectMapping  mappingForClass:[ResponseMessage class]];
    [responseMappingObject addAttributeMappingsFromDictionary:@{
                                                             uStatus: @"status",
                                                             uMessage: @"message",
                                                             }];
    [responseMappingObject addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"newsfeeds"
                                                                                       toKeyPath:@"newsfeeds"
                                                                                     withMapping:newsFeedMappingObject]];



    RKObjectMapping * contentMappingObject = [RKObjectMapping  mappingForClass:[Content class]];
    [contentMappingObject addAttributeMappingsFromDictionary:@{
                                                               @"id": @"contentId",
                                                                }];
    [newsFeedMappingObject addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"content"
                                                                                          toKeyPath:@"cont"
                                                                                        withMapping:contentMappingObject]];


    RKObjectMapping * postContentMappingObject = [RKObjectMapping  mappingForClass:[PostContent class]];
    [postContentMappingObject addAttributeMappingsFromDictionary:@{
                                                               @"type": @"type",
                                                               }];
    [contentMappingObject addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"contents"
                                                                                         toKeyPath:@"contents"
                                                                                       withMapping:postContentMappingObject]];




    RKObjectMapping * postMappingObject = [RKObjectMapping  mappingForClass:[Post class]];
    [postMappingObject addAttributeMappingsFromDictionary:@{
                                                            @"title" :  @"title"
                  }];

    RKDynamicMapping* dynamicMapping = [RKDynamicMapping new];
    [postMappingObject addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"post" toKeyPath:@"content" withMapping:dynamicMapping]];


    // Connect a response descriptor for our dynamic mapping
    RKResponseDescriptor *dynamicResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:dynamicMapping method:RKRequestMethodAny pathPattern:nil keyPath:@"content" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
    [[RKObjectManager sharedManager] addResponseDescriptor:dynamicResponseDescriptor];


    // Option 2: Configure the dynamic mapping via a block
    [dynamicMapping setObjectMappingForRepresentationBlock:^RKObjectMapping *(id representation) {
        if ([[representation valueForKey:@"content"] isKindOfClass:[NSDictionary class]]) {
            return postMappingObject;
        }
        return nil;
    }];

    [postContentMappingObject addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"content"
                                                                                         toKeyPath:@"post"
                                                                                       withMapping:postMappingObject]];



    NSString *urlString = [NSString stringWithFormat:@"%@%@%@&userId=%@&startDate=%@&count=%d&scanForward=%@",uServiceUrl,uGetNewsFeedsRequest,accountId,userId,startDate,count,isForward];
    NSString* encodedUrl = [urlString stringByAddingPercentEncodingWithAllowedCharacters:
                            [NSCharacterSet URLQueryAllowedCharacterSet]];
    NSURL *getNewsRequestUrl = [NSURL URLWithString:encodedUrl];

    RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:responseMappingObject method:RKRequestMethodAny pathPattern:nil keyPath:@"" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];

    [self getWithUrlString:getNewsRequestUrl withMappingObject:responseMappingObject andResponseDescriptors:@[responseDescriptor, dynamicResponseDescriptor] withSuccess:successBlock withFail:failBlock];
1
Why is it sometimes a string? You'll need to use a custom dynamic mapping... - Wain
Response is in such a way. I have no control over it. Will I need to change postMappingObject? - Ranjith
I'm sorry but can you elaborate. I'm confused. - Ranjith

1 Answers

0
votes

You need to change postMappingObject to be an instance of RKDynamicMapping which checks the data that it's provided with to see what it is and returns an appropriate mapping that will actually be used to process that data. The check is to determine if the payload is a string or a dictionary.