Non-deprecated means of setting object mapping - objective-c

I have a Ruby On Rails local server running which serves me the following JSON:
[ { "content" : "Here is content",
"created_at" : "2012-10-07T01:06:51Z",
"id" : 4,
"name" : "Joe",
"title" : "Title 1",
"updated_at" : "2012-10-07T01:06:51Z"
},
{ "content" : "Here is content",
"created_at" : "2012-10-07T01:07:09Z",
"id" : 5,
"name" : "John",
"title" : "Title2",
"updated_at" : "2012-10-07T01:07:09Z"
}
]
I am using RestKit to parse this into Post model objects like so:
- (void)loadObjects
{
RKObjectMapping *objectMapping = [RKObjectMapping mappingForClass:[Post class]];
[objectMapping mapKeyPath:#"id" toAttribute:#"postId"];
[objectMapping mapKeyPath:#"created_at" toAttribute:#"createdAt"];
[objectMapping mapKeyPath:#"content" toAttribute:#"content"];
[objectMapping mapKeyPath:#"title" toAttribute:#"title"];
[objectMapping mapKeyPath:#"name" toAttribute:#"name"];
[objectMapping mapKeyPath:#"updated_at" toAttribute:#"updatedAt"];
RKObjectManager* manager = [RKObjectManager objectManagerWithBaseURLString:#"http://localhost:3000/"];
[manager loadObjectsAtResourcePath:#"/posts" objectMapping:objectMapping delegate:self];
}
- (void)objectLoader:(RKObjectLoader *)objectLoader didLoadObjects:(NSArray *)objects {
NSLog(#"%#", objects);
}
This works fine, however the loadObjectsAtResourcePath:objectMapping:delegate: is deprecated. I assume I should therefore be using loadObjectsAtResourcePath:delegate:, but I cannot figure out a way to set the objectMapping. Any thoughts?
Update
I am now setting the delegate like so:
[manager loadObjectsAtResourcePath:#"/posts" usingBlock:^(RKObjectLoader *loader) {
loader.objectMapping = objectMapping;
loader.delegate = self;
}];

The restkit documentation says that if you use loadObjectsAtResourcePath:usingBlock: you can set the objectMapping from inside the a block.
- (void)loadObjectUsingBlockExample {
[[RKObjectManager sharedManager] loadObjectsAtResourcePath:#"/monkeys.json" usingBlock:^(RKObjectLoader *loader) {
loader.objectMapping = [[RKObjectManager sharedManager].mappingProvider objectMappingForClass:[Monkey class]];
}];
}

Related

Post complex json using RestKit in Objective-C

I'm having an issue posting json by using RestKit, but I can't find what I'm doing wrong.
The request json sample is:
{
"Name": "sample string 1",
"Interests": {
"Array": [
1,
2,
3
]
}
}
My code:
RKObjectMapping *requestMapping = [RKObjectMapping requestMapping];
[requestMapping addAttributeMappingsFromDictionary:#{#"Name": #"Name"}];
RKObjectMapping *interestsMapping = [RKObjectMapping mappingForClass:[NSMutableDictionary class]];
RKObjectMapping *interestIDMapping = [RKObjectMapping mappingForClass:[KLInterest class]];
[interestIDMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:nil toKeyPath:#"InterestID"]];
[interestsMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"Array" toKeyPath:#"Array" withMapping:interestIDMapping]];
[requestMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"Interests" toKeyPath:#"Interests" withMapping:interestsMapping]];
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:requestMapping objectClass:[NSMutableDictionary class] rootKeyPath:nil method:RKRequestMethodPOST];
[self.objectManager addRequestDescriptor:requestDescriptor];
NSDictionary *data = [business toDictionary];
[self sendRequest:#"api/Business/Create" Method:#"POST" Data:data withCallback:^(BOOL success, NSDictionary response, NSError error) {
callback(success, response, error);
}];
KLInterestID.h
#interface KLInterestID : NSObject
#property (nonatomic) NSNumber *InterestID;
#end
Please let me know what I'm doing wrong. I'm not familiar with the relationshipMappingFromKeyPath and attributeMappingFromKeyPath:nil functions.
I'm not sure how to send int array.
Thanks

RestKit - Data Mapping

I'm new in RestKit.
Can someone help me with mapping. I have JSON and I need to read and save data from JSON. How I can do it?
{"data": {
"viewer": {
"themes": {
"edges": [
{
"node": {
"id": "61c39",
"name": "ff"
}
}
{
"node": {
"id": "dd95af4b-"",
"name": "growth",
}
}
]
}
}
}
}
Here is a part of my code for mapping:
// Defines mapping for DefaultThemes
RKEntityMapping *mappingDefaultTheme = [RKEntityMapping mappingForEntityForName:#"DefaultThemeData"
inManagedObjectStore:self.managedObjectStore];
mappingDefaultTheme.identificationAttributes = #[#"themeId"];
[mappingDefaultTheme addAttributeMappingsFromDictionary:#{ #"node.id" : #"themeId", #"node.name" : #"name"}];
RKResponseDescriptor *themeDefaultListResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mappingDefaultTheme
method:RKRequestMethodGET
pathPattern:#"graphql"
keyPath:#"edges.node"
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
I have error when I running the app:
Error: No mappable object representations were found at the key paths searched.
So I need to know, how I should do data mapping?
The key path data.viwer.themes.edges.node is too deep because you're trying to drill down into an array and that isn't possible. The longest key path you can have is data.viwer.themes.edges and then the mapping will process each of the objects containing 'nodes'.
Here is my solution:
RKObjectMapping* chartDataDetailMapping = [RKObjectMapping mappingForClass:[MADefaultThemeData class]];
[chartDataDetailMapping addAttributeMappingsFromDictionary:#{#"id": #"themeId",
#"name": #"name"}];
RKObjectMapping* chartDataMapping = [RKObjectMapping mappingForClass:[MANode class]];
[chartDataMapping addAttributeMappingsFromDictionary:#{#"edges":#"edges"}];
RKObjectMapping* alertInstanceMapping = [RKObjectMapping mappingForClass:[MADefaultThemeList class]];
[alertInstanceMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"edges"
toKeyPath:#"edges"
withMapping:chartDataMapping]];
[chartDataMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"node"
toKeyPath:#"themeData"
withMapping:chartDataDetailMapping]];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:alertInstanceMapping
method:RKRequestMethodPOST
pathPattern:#"graphql"
keyPath:#"data.viewer.themes"
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[self addResponseDescriptor:responseDescriptor];

RestKit nested relationships

Working with RestKit, I'm trying to map the following JSON.
{
"userID": 1,
"collections": [
{
"collectionID": 120,
"friends": [
{
"friendID": 6,
"orders": [
{
"orderID": 1,
"name": "Small"
}
]
}
]
},
{
"collectionID": 123,
"friends": [
{
"friendID": 6,
"orders": [
{
"orderID": 2,
"name": "Medium"
}
]
}
]
}
]
}
I'm utilising RestKit and MagicalRecord - setup code, mapping and relationships below
NSURL *modelURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"Model" ofType:#"momd"]];
NSManagedObjectModel *managedObjectModel = [[[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL] mutableCopy];
RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel];
NSString *storePath = [RKApplicationDataDirectory() stringByAppendingPathComponent:#"db.sqlite"];
[managedObjectStore addSQLitePersistentStoreAtPath:storePath fromSeedDatabaseAtPath:nil withConfiguration:nil options:nil error:nil];
[managedObjectStore createManagedObjectContexts];
// Configure MagicalRecord to use RestKit's Core Data stack
[NSPersistentStoreCoordinator MR_setDefaultStoreCoordinator:managedObjectStore.persistentStoreCoordinator];
[NSManagedObjectContext MR_setRootSavingContext:managedObjectStore.persistentStoreManagedObjectContext];
[NSManagedObjectContext MR_setDefaultContext:managedObjectStore.mainQueueManagedObjectContext];
RKObjectManager *objectManager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:#"http://127.0.0.1:3500"]];
objectManager.managedObjectStore = managedObjectStore;
RKEntityMapping *appMapping = [RKEntityMapping mappingForEntityForName:#"App" inManagedObjectStore:managedObjectStore];
appMapping.identificationAttributes = #[ #"userID" ];
RKEntityMapping *collectionMapping = [RKEntityMapping mappingForEntityForName:#"Collection" inManagedObjectStore:managedObjectStore];
collectionMapping.identificationAttributes = #[ #"collectionID" ];
[collectionMapping addAttributeMappingsFromArray:#[#"collectionID"]];
RKEntityMapping *friendMapping = [RKEntityMapping mappingForEntityForName:#"Friend" inManagedObjectStore:managedObjectStore];
friendMapping.identificationAttributes = #[ #"friendID" ];
[friendMapping addAttributeMappingsFromArray:#[#"friendID"]];
RKEntityMapping *orderMapping = [RKEntityMapping mappingForEntityForName:#"Order" inManagedObjectStore:managedObjectStore];
orderMapping.identificationAttributes = #[ #"orderID" ];
[orderMapping addAttributeMappingsFromArray:#[#"orderID", #"name"]];
RKRelationshipMapping *appCollectionRelationship = [RKRelationshipMapping relationshipMappingFromKeyPath:#"collections" toKeyPath:#"collections" withMapping:collectionMapping];
[appMapping addPropertyMapping:appCollectionRelationship];
RKRelationshipMapping *collectionFriendRelationship = [RKRelationshipMapping relationshipMappingFromKeyPath:#"friends" toKeyPath:#"friends" withMapping:friendMapping];
[collectionMapping addPropertyMapping:collectionFriendRelationship];
RKRelationshipMapping *friendsOrderRelationship = [RKRelationshipMapping relationshipMappingFromKeyPath:#"orders" toKeyPath:#"orders" withMapping:orderMapping];
[friendsOrderRelationship setAssignmentPolicy:RKUnionAssignmentPolicy];
[friendMapping addPropertyMapping:friendsOrderRelationship];
Then, querying the /test route on my API (which outputs the JSON block above) with the below console out...
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:appMapping method:RKRequestMethodAny pathPattern:nil keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptor:responseDescriptor];
[objectManager getObjectsAtPath:#"/test" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
App *app = [mappingResult firstObject];
for (Collection *collection in app.collections) {
NSLog(#"collectionID = %#", collection.collectionID);
for (Friend *friend in collection.friends) {
NSLog(#"friendID = %#", friend.friendID);
for (Order *order in friend.orders) {
NSLog(#"Name = %#", order.name);
}
}
}
} failure:^(RKObjectRequestOperation *operation, NSError *error) {}];
Provides the following output - notice both Name's are Medium, not one Small and the other Medium.
collectionID = 120
friendID = 6
Name = Medium
Name = Small
collectionID = 123
friendID = 6
Name = Medium
Name = Small
Why would this be happening? I'm going to guess that it's because both friend ID's are the same, even though they're under different collections...
This is because you have identificationAttributes = #[ #"friendID" ]; and the default relationship connection rule for relationships rather than replacement. So, the second mapping finds the friend created by the first mapping and replaces the order relationship contents.
You can't realistically change the unique identifier based on the JSON you show, but you might want to examine that (in relation to your object graph requirements).
Also / alternatively, see this answer for details of how to change the relationship assignment policy so that the original relationship contents aren't lost.

Restkit 0.20 keypath error 1001

I used Restkit 0.20 (first time) for posting objects to a Rails server via JSON, and I 've been stuck for the last days with an annoying mapping error. Got 2 objects Picture and Item.
Picture
{
"base64" : null,
"id" : 1,
"created_at" : "2013-08-28T15:08:49Z",
"user_nickname" : "user_name",
"tag" : "ALPHA",
"nbitems" : null,
"path" : {
"url" : "https://www.mywebsite/pictures/1/default.jpg"
},
"updated_at" : "2013-08-28T15:08:49Z",
"user_id" : 1
}
Item
{
"base64" : null,
"picture_id" : 1,
"id" : 1,
"created_at" : "2013-08-28T15:10:54Z",
"itemurl" : {
"url" : "https://www.mywebsite/pictures/1/item1.png"
},
"nickname" : "",
"user_id" : 1,
"updated_at" : "2013-08-28T15:10:54Z"
}
Here's my mapping in the AppDelegate.m
//Mapping users
RKEntityMapping *userMapping = [RKEntityMapping mappingForEntityForName:NSStringFromClass([User class]) inManagedObjectStore:manager.managedObjectStore];
[userMapping addAttributeMappingsFromDictionary:#{
#"id" : #"user_id",
#"email" : #"email",
#"nickname" : #"nickname",
#"created_at" : #"createdAt"
}];
userMapping.identificationAttributes = #[ #"user_id" ];
//Mapping paths
RKEntityMapping *pathMapping = [RKEntityMapping mappingForEntityForName:NSStringFromClass([Path class]) inManagedObjectStore:manager.managedObjectStore];
[pathMapping addAttributeMappingsFromDictionary:#{
#"url" : #"url"
}];
//Mapping itemURL
RKEntityMapping *itemURLMapping = [RKEntityMapping mappingForEntityForName:NSStringFromClass([ItemURL class]) inManagedObjectStore:manager.managedObjectStore];
[pathMapping addAttributeMappingsFromDictionary:#{
#"url" : #"url"
}];
//Mapping pictures
RKEntityMapping *pictureMapping = [RKEntityMapping mappingForEntityForName:NSStringFromClass([Picture class]) inManagedObjectStore:managedObjectStore];
[pictureMapping addAttributeMappingsFromDictionary:#{
#"id" : #"picture_id",
#"user_id" : #"user_id",
#"user_nickname" : #"user_nickname",
#"nbitems" : #"nbitems",
#"tag" : #"tag",
#"base64" : #"base64",
#"created_at" : #"createdAt"
}];
pictureMapping.identificationAttributes = #[ #"picture_id"];
[pictureMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"path" toKeyPath:#"path" withMapping:pathMapping]];
[manager addResponseDescriptorsFromArray:#[
[RKResponseDescriptor responseDescriptorWithMapping:pictureMapping
pathPattern:#"pictures"
keyPath:nil
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)]
]];
RKObjectMapping *pictureRequestMapping = [RKObjectMapping requestMapping];
[pictureRequestMapping addAttributeMappingsFromArray:#[#"user_id", #"user_nickname", #"tag", #"base64", #"path"]];
RKRequestDescriptor *pictureRequestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:pictureRequestMapping objectClass:[Picture class] rootKeyPath:#"picture" method:RKRequestMethodAny];
[manager addRequestDescriptor:pictureRequestDescriptor];
//Mapping items
RKEntityMapping *itemMapping = [RKEntityMapping mappingForEntityForName:NSStringFromClass([Item class]) inManagedObjectStore:managedObjectStore];
itemMapping.identificationAttributes = #[ #"item_id"];
[itemMapping addAttributeMappingsFromDictionary:#{
#"id" : #"item_id",
#"picture_id" : #"picture_id",
#"user_id" : #"user_id",
#"nickname" : #"nickname",
#"base64" : #"base64",
#"created_at" : #"createdAt"
}];
RKRelationshipMapping *itemURLRelation = [RKRelationshipMapping relationshipMappingFromKeyPath:#"itemurl" toKeyPath:#"itemurl" withMapping:itemURLMapping];
[itemMapping addPropertyMapping:itemURLRelation];
RKResponseDescriptor *itemDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:itemMapping
pathPattern:#"items"
keyPath:nil
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[manager addResponseDescriptor:itemDescriptor];
RKObjectMapping *itemRequestMapping = [RKObjectMapping requestMapping];
[itemRequestMapping addAttributeMappingsFromArray:#[#"picture_id", #"user_id", #"nickname", #"base64", #"itemurl"]];
RKRequestDescriptor *itemRequestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:itemRequestMapping objectClass:[Item class] rootKeyPath:#"item" method:RKRequestMethodAny];
[manager addRequestDescriptor:itemRequestDescriptor];
I post a Picture instance in a ViewController and it works perfectly
- (void)uploadPicture:(UIImage *)chosenImage{
NSManagedObjectContext *moc = [RKManagedObjectStore defaultStore].mainQueueManagedObjectContext;
UIImage *resizedImage = [self scaleImage:chosenImage maxWidth:640 maxHeight:960];
NSString *imageEncoded = [self image2jpg2String:resizedImage];
Picture *picture = [Picture insertInManagedObjectContext:moc];
picture.user_id = userId;
picture.user_nickname = #"user_nickname";
picture.tag = #"ALPHA";
picture.base64 = imageEncoded;
[[RKObjectManager sharedManager] postObject:picture path:#"pictures" parameters:nil success:nil failure:^(RKObjectRequestOperation *operation, NSError *error) { NSLog(#"Error: %#",error);}];
}
I try to do the same with an Item instance in another controller
- (void)uploadItem{
NSManagedObjectContext *mocFVC = [RKManagedObjectStore defaultStore].mainQueueManagedObjectContext;
NSNumber *userId = [NSNumber numberWithInt:1];
UIImage *itemImage = self.itemImage.image;
UIImage *resizedItem = [self scaleImage:itemImage maxWidth:640 maxHeight:960];
NSString *itemEncoded = [self image2png2String:resizedItem];
Item *item = [Item insertInManagedObjectContext:mocFVC];
item.user_id = userId;
item.nickname = #"user_nickname";
item.picture_id = pictureToDisplay.picture_id;
item.base64 = itemEncoded;
[[RKObjectManager sharedManager] postObject:item path:#"items" parameters:nil success:nil failure:^(RKObjectRequestOperation *operation, NSError *error) { NSLog(#"Error: %#",error);}];
}
But unless I comment the item.base64, xcode always returns the following error
2013-08-28 22:51:41.116 MYPROJECT[4588:1603] E restkit.network:RKObjectRequestOperation.m:243 POST 'http://www.mywebsite/items' (422 Unprocessable Entity / 0 objects) [request=0.6791s mapping=0.0000s total=0.7111s]: Error Domain=org.restkit.RestKit.ErrorDomain Code=1001 "No mappable object representations were found at the key paths searched."
UserInfo=0x1e8af330 {DetailedErrors=(), NSLocalizedFailureReason=The mapping operation was unable to find any nested object representations at the key paths searched: error
The representation inputted to the mapper was found to contain nested object representations at the following key paths: itemurl
This likely indicates that you have misconfigured the key paths for your mappings., NSLocalizedDescription=No mappable object representations were found at the key paths searched., keyPath=null}
2013-08-28 22:51:41.119 MYPROJECT[4588:907] Error: Error Domain=org.restkit.RestKit.ErrorDomain Code=1001 "No mappable object representations were found at the key paths searched." UserInfo=0x1e8af330 {DetailedErrors=(), NSLocalizedFailureReason=The mapping operation was unable to find any nested object representations at the key paths searched: error
The representation inputted to the mapper was found to contain nested object representations at the following key paths: itemurl
This likely indicates that you have misconfigured the key paths for your mappings., NSLocalizedDescription=No mappable object representations were found at the key paths searched., keyPath=null}
I checked a lot of post on stackoverflow and read the restkit doc before posting, but don't understand why it doesn't work for my item since it's code and picture model are very closed to the one I use for my Item class. Am I missing something ? Any idea ? :)
#Wain the logs didn't show anything
Turns out the Restkit part was correct. The error was happening in my base64/upload function in the model.
def base64=(data)
# decode data and create stream on them
filename = "#{self.user_id}.png"
io = CarrierStringIO.new(filename, Base64.decode64(data))
# this will do the thing (photo is mounted carrierwave uploader)
self.path = io
end
The filename line works in a webbrowser but not using JSON. #weird
Had to change the path of the file to keep the user_id as data

RestKit - Sending POST & Receive Response mapped

So, i m using RestKit version 0.20 and i m successfully sending a POST request as JSON. My Server backend (Java REST WS (Jersey)) is mapping everything right, aswell Restkit.
My Problem is now that i m sending a different Object back as that I have Post. I have following mapping setup in RestKit:
- (void)createUserAccount:(DeviceDTO *)devDTO :(UserDTO *)userDTO block:(void (^)(id))block{
id errorCode __block;
// Configure a request mapping for our Article class. We want to send back title, body, and publicationDate
RKObjectMapping* deviceRequestMapping = [RKObjectMapping requestMapping];
[deviceRequestMapping addAttributeMappingsFromArray:#[ #"model", #"name", #"systemName", #"systemVersion", #"devToken" ]];
RKObjectMapping* msRequestMapping = [RKObjectMapping requestMapping];
[msRequestMapping addAttributeMappingsFromArray:#[ #"validSince", #"validTill" ]];
RKObjectMapping* countryRequestMapping = [RKObjectMapping requestMapping];
[countryRequestMapping addAttributeMappingsFromArray:#[ #"idNumberDTO", #"iso2DTO", #"short_nameDTO", #"calling_codeDTO" ]];
RKObjectMapping* contactsRequestMapping = [RKObjectMapping requestMapping];
[contactsRequestMapping addAttributeMappingsFromArray:#[ #"fullName", #"phoneNumber"]];
RKObjectMapping* userRequestMapping = [RKObjectMapping requestMapping];
[userRequestMapping addAttributeMappingsFromArray:#[ #"displayName", #"phoneNumber", #"status", #"userID", #"realName" ]];
[userRequestMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"deviceInfo" toKeyPath:#"device" withMapping:deviceRequestMapping]];
[userRequestMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"memberShipDetails" toKeyPath:#"memberShip" withMapping:msRequestMapping]];
[userRequestMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"country" toKeyPath:#"country" withMapping:countryRequestMapping]];
[userRequestMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"contacts" toKeyPath:#"contacts" withMapping:contactsRequestMapping]];
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:userRequestMapping objectClass:[UserDTO class] rootKeyPath:nil];
//Create Objects
UserDTO *user = [[UserDTO alloc]init];
..........
DeviceDTO *device = [[DeviceDTO alloc]init];
..........
user.deviceInfo = device;
MemberShipDTO *ms = [[MemberShipDTO alloc]init];
.......
user.memberShipDetails = ms;
RKObjectMapping *errorMapping = [RKObjectMapping mappingForClass:[ErrorMapping class]];
[errorMapping addAttributeMappingsFromArray:#[ #"errorCode", #"errorMessage" ]];
RKObjectMapping* deviceRespMapping = [RKObjectMapping mappingForClass:[DeviceDTO class]];
[deviceRespMapping addAttributeMappingsFromArray:#[ #"model", #"name", #"systemName", #"systemVersion", #"devToken" ]];
RKObjectMapping* msRespMapping = [RKObjectMapping mappingForClass:[MemberShipDTO class]];
[msRespMapping addAttributeMappingsFromArray:#[ #"validSince", #"validTill" ]];
RKObjectMapping* contactsRespMapping = [RKObjectMapping mappingForClass:[ContactDTO class]];
[contactsRespMapping addAttributeMappingsFromArray:#[ #"fullName", #"phoneNumber"]];
RKObjectMapping* userRespMapping = [RKObjectMapping mappingForClass:[UserDTO class]];
[userRespMapping addAttributeMappingsFromArray:#[ #"displayName", #"phoneNumber", #"status", #"userID", #"realName" ]];
[userRespMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"deviceInfo" toKeyPath:#"device" withMapping:deviceRespMapping]];
[userRespMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"memberShipDetails" toKeyPath:#"memberShip" withMapping:msRespMapping]];
[userRespMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"country" toKeyPath:#"country" withMapping:countryRequestMapping]];
[userRespMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"contacts" toKeyPath:#"contacts" withMapping:contactsRespMapping]];
[errorMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"user" toKeyPath:#"user" withMapping:userRespMapping]];
RKResponseDescriptor *errorDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:errorMapping pathPattern:nil keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[RKMIMETypeSerialization registerClass:[RKNSJSONSerialization class] forMIMEType:#"application/json"];
[[RKObjectManager sharedManager] setRequestSerializationMIMEType:RKMIMETypeJSON];
[[RKObjectManager sharedManager] setAcceptHeaderWithMIMEType:RKMIMETypeJSON];
[[RKObjectManager sharedManager] addRequestDescriptor:requestDescriptor];
[[RKObjectManager sharedManager] addResponseDescriptor:errorDescriptor];
[[RKObjectManager sharedManager] postObject:user path:#"user/integrate" parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult){
NSArray* statuses = [mappingResult array];
NSLog(#"Loaded statuses: %#", statuses);
errorCode = [statuses objectAtIndex:0];
NSLog(#"errorCode == %#", errorCode);
block(errorCode);
RKLogInfo(#"Load collection of Articles: %#", mappingResult.array);
}failure:^(RKObjectRequestOperation *operation, NSError *error) {
block(nil);
RKLogError(#"Operation failed with error: %#", error);
}];
}
My JSON on my request is fine & the response is also fine:
{
"errorMessage": null,
"errorCode": 190,
"user": {
"displayName": "Saif",
"phoneNumber": "+xxx",
"userID": "xxx",
"country": {
"idNumberDTO": 83,
"short_nameDTO": "Germany",
"calling_codeDTO": "+49",
"iso2DTO": "DE"
},
"device": {
"devToken": "xxx",
"model": "iPhone",
"name": "Saifs iPhone",
"systemName": "iPhone OS",
"systemVersion": "6.1.4",
"id": null
},
"memberShip": {
"validSince": 1376047810000,
"validTill": 1407583810000,
"id": null
},
"contacts": [
{
"fullName": "xxx",
"phoneNumber": "xxx"
},
{
"fullName": "xxx",
"phoneNumber": "xxx"
},
....,
....,
....
],
"id": null
}
}
On my RK methode i get on this line:
errorCode = [statuses objectAtIndex:0];
this Error:
2013-08-09 13:30:12.246 xxx![19310:440f] W restkit.object_mapping:RKMapperOperation.m:99 Adding mapping error: Expected an object mapping for class of type 'UserDTO', provider returned one for 'ErrorMapping'
2013-08-09 13:30:12.247 xxx![19310:440f] I restkit.network:RKObjectRequestOperation.m:250 POST 'http://192.168.2.115:8080/WAZZUUPWS/rest/service/user/integrate' (200 OK / 0 objects) [request=1.3406s mapping=0.0047s total=1.3461s]
2013-08-09 13:30:12.249 xxx![19310:907] Loaded statuses: (
)
2013-08-09 13:30:12.250 xxx![19310:907] *** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array'
It looks like the response couldnt be mapped and thats why the Resultarray is empty. Any idea how i can map a complex object from a response?
From the Restkit documentation:
By default when postObject or putObject are used, RestKit is automatically going to try to map the JSON result into the sourceObject that was posted.
In your code, you are posting an UserDTO instance and receiving a JSON response that should map to ErrorMapping. Hence, you are getting RKMappingErrorTypeMismatch from Restkit.
As explained in the documentation, instead of using post, you can create an RKRequestOperation yourself and nil the target object to override the defaults.
RKObjectRequestOperation *operation = [[RKObjectManager sharedManager] appropriateObjectRequestOperationWithObject:user
method:RKRequestMethodPOST
path:#"user/integrate"
parameters:nil];
operation.targetObject = nil;
[operation setCompletionBlockWithSuccess:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
DLog(#"integrated user: %#", mappingResult.firstObject);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
DLog(#"error integrating user: %#", user);
}];
However, if you can modify the backend, I'd prefer to change the returned JSON. Instead of including the error codes in the JSON response, use relevant (HTTP) response status codes and include only domain model specific entities in your responses.