I am implementing a simple iOS app that consumes reddit feeds and I need to show the feed comments. I am using RESTKit to do the ORM part and I am having an annoyance with mapping the comments.
Reddit comments can have replies and the replies can have replies and so on. It's a tree of comments. This is no big deal. The problem is that among the children nodes there might exist one that's different (used to sign that there are more comments to load on that particular thread).
Here's a JSON example:
"replies":{
"data":
{
"after": null,
"before": null,
"children":
[
{
"data":
{
"approved_by": null,
"author": "InstaRamen",
"author_flair_css_class": null,
"author_flair_text": null,
"banned_by": null,
"body": "that or he counted it all wrong",
"body_html":"<div class=\"md\"><p>that or he counted it all wrong</p>\n</div>",
"controversiality": 0,
"created": 1405093511,
"created_utc": 1405064711,
"distinguished": null,
"downs": 0,
"edited": false,
"gilded": 0
"id": "ciubfdk",
"likes": null,
"link_id": "t3_2ae8oa",
"name": "t1_ciubfdk",
"num_reports": null,
"parent_id": "t1_ciuao19",
"replies":
{
"data":
{
"after": null,
"before": null,
"children":
[
{
"data":
{
"approved_by": null,
"author": "Everlasting",
"author_flair_css_class": null,
"author_flair_text": null,
"banned_by": null,
"body": "3, sir.",
"body_html":"<div class=\"md\"><p>3, sir.</p>\n</div>",
"controversiality": 0,
"created": 1405093986,
"created_utc": 1405065186,
"distinguished": null,
"downs": 0,
"edited": false,
"gilded": 0,
"id": "ciubj8h",
"likes": null,
"link_id": "t3_2ae8oa",
"name": "t1_ciubj8h",
"num_reports": null,
"parent_id": "t1_ciubfdk",
"replies":
{
"data":
{
"after": null,
"before": null,
"children":
[
{
"data":
{
"children":
[
"ciublgq"
],
"count": 0,
"id":"ciublgq",
"name":"t1_ciublgq",
"parent_id": "t1_ciubj8h"
},
"kind": "more"
}
],
"modhash": ""
},
"kind": "Listing"
},...
So, you can see that the typical comment replies has a structure of
replies
|-data
|-children
|-data
|- #comment key/values
But the "Load more" item has a structure of:
replies
|-data
|-children
|-data
|-children
|-more loading info...
My DataObject is:
@interface RedditComment : NSObject
@property (nonatomic, copy) NSString *author;
@property (nonatomic, readwrite) NSInteger createdUTC;
@property (nonatomic, readwrite) NSInteger score;
@property (nonatomic, copy) NSString *subreddit;
@property (nonatomic, copy) NSString *subredditId;
@property (nonatomic, readwrite) NSInteger ups;
@property (nonatomic, copy) NSString *body;
@property (nonatomic, copy) NSArray *replies;
+ (RKObjectMapping*)restKitMapping;
@end
And my mapping implementation is:
@implementation RedditComment
+ (RKObjectMapping*)restKitMapping;
{
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[self class]];
[mapping addAttributeMappingsFromDictionary:@{
@"author": @"author",
@"created_utc": @"createdUTC",
@"score": @"score",
@"subreddit": @"subreddit",
@"subreddit_id": @"subredditId",
@"body": @"body",
@"ups": @"ups",
}];
[mapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"replies" toKeyPath:@"replies" withMapping:mapping]];
return mapping;
}
@end
This yields an error:
*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<__NSCFConstantString 0x1daa0d0> valueForUndefinedKey:]: this class is not key value coding-compliant for the key body.'
This is because the "Load more" node doesn't have a body key (it's missing other keys as well, but this is the first one that RESTKit complains about).
I've tried to use a dynamic mapping block to change the mapping in runtime but couldn't figure out how to isolate the problematic node (i.e. the "Load More").
My question is how can I distinguish between both possible values in "replies" JSON nodes?
Can I have two mappings for the same partial key? That is a mapping for replies > data > children > data and another to replies > data > children > data > children. If so how to do it?
Or is there anything wrong in my line of thinking?
Thanks in advance to everyone that is able to help or that simply take the time to read... ;-)
EDIT including response descriptor
As requested on comments here's the RKResponseDescriptor:
RKResponseDescriptor *commentResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:[PPRedditComment restKitMapping]
method:RKRequestMethodAny
pathPattern:nil
keyPath:@"data"
statusCodes:nil];
EDIT #2
including a "good comment" node to show what I am interested to map to my DO
"data":
{
"approved_by": null,
"author": "PerimeterBlue",
"author_flair_css_class":null,
"author_flair_text":null,
"banned_by":null,
"body": "This actually looks really cool.",
"body_html": "<div class=\"md\"><p>This actually looks really cool.</p>\n</div>",
"controversiality":0,
"created": 1405095679,
"created_utc": 1405066879,
"distinguished":null,
"downs": 0,
"edited": false,
"gilded": 0,
"id": "ciubwld",
"likes":null,
"link_id": "t3_2aelr4",
"name": "t1_ciubwld",
"num_reports": null,
"parent_id": "t3_2aelr4",
"replies": {...},
"saved": false,
"score": 48,
"score_hidden": false,
"subreddit": "gaming",
"subreddit_id": "t5_2qh03",
"ups": 48
}
children
ordata
in your mapping if that is the only mapping? – Wain