Here is the setup: we have an API that provides data in JSON format, and want to use Restkit to map to two core data objects. The objects "products" and "resources", and they are related with a many-to-one relationship. 1 product can be related to many resources. Thus, we have the Product:
@class Resource;
@interface Product : NSManagedObject
@property (nonatomic, retain) NSNumber * productid;
@property (nonatomic, retain) NSString * descriptiontext;
@property (nonatomic, retain) NSString * brand;
@property (nonatomic, retain) NSSet *productResource;
@end
and the Resources
@class Product;
@interface Resource : NSManagedObject
@property (nonatomic, retain) NSNumber * productid;
@property (nonatomic, retain) NSNumber * resourceid;
@property (nonatomic, retain) NSString * url;
@end
We have a problem with using Restkit for a situation where the API we are accessing provides its data in the following JSON format that doesn't correspond straightforwardly to the Core Data objects. Thus, for each product, the API is returning the related resources like this:
listproducts: [
{ productid: 2,
description: "description of product2",
brand: "brand 2",
resource: [ { resourceid: 22, url: "img_3786.jpg" },
{ resourceid: 23, url: "tpa-plated-dessert.jpg" } ],
},
{ productid: 3,
description: "description of product3",
brand: "brand 3",
resource: [ { resourceid: 15, url: "img_3786.jpg" } ],
},
]
We know how to use Restkit to map correctly to the core data objects, IF the API provided the products and the resources separately. In that case, we can just use:
RKEntityMapping *productMapping = [RKEntityMapping mappingForEntityForName:@"Product" inManagedObjectStore:managedObjectStore];
productMapping.identificationAttributes = @[ @"productid" ];
[productMapping addAttributeMappingsFromDictionary:@{
@"productid" : @"productid",
@"description" : @"descriptiontext",
@"brand" : @"brand"
}];
RKEntityMapping *resourceMapping = [RKEntityMapping mappingForEntityForName:@"Resource" inManagedObjectStore:managedObjectStore];
resourceMapping.identificationAttributes = @[ @"resourceid" ];
[resourceMapping addAttributeMappingsFromDictionary:@{
@"resourceid" : @"resourceid",
@"productid" : @"productid",
@"url" : @"url",
}];
[productMapping addConnectionForRelationship:@"productResource" connectedBy:@"productid" ];
However, the API that we have is a nested one that has already done some of the "work" by providing the appropriate resources whose productid matches that of the product, so [productMapping addConnectionForRelationship:@"productResource" connectedBy:@"productid" ];
is not appropriate. Should we try something else, like
[productMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:@"listproducts.resource" toKeyPath:@"listproducts" withMapping:resourceMapping]];
? https://github.com/RestKit/RestKit/wiki/Object-mapping gives an example with nested JSON, but that is a different case. Here, the resources are nested and come without explicit productid
, but take the productid
from the parent .. how do we use Restkit with this API?
In other words, we want the NSSet productResource
to be correctly populated, and corresponding Resource objects to be populated, but currently the NSSet is empty.
Here are the response descriptors:
RKResponseDescriptor *productRD = [RKResponseDescriptor responseDescriptorWithMapping:productMapping
method:RKRequestMethodGET
pathPattern:nil
keyPath:@"listproducts"
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
RKResponseDescriptor *resourceRD = [RKResponseDescriptor responseDescriptorWithMapping:resourceMapping
method:RKRequestMethodGET
pathPattern:nil
keyPath:@"resource"
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptorsFromArray:@[productRD, resourceRD]];