I have an entity Comments. When I perform a rest operation, i get a response which has fields such as
{
"status": "succeed"
}
I want to process these fields to know if the operation was successful or not but I dont want to add status to comment class because it doesnt belogn there.
RKObjectManager *sharedRKObjectManager = [RKObjectManager sharedManager];
RKManagedObjectStore *managedObjectStore = [sharedRKObjectManager managedObjectStore];
// Create a mapping for the comment entity
RKEntityMapping *responseMapping = [RKEntityMapping mappingForEntityForName:ENTITY_COMMENT inManagedObjectStore:managedObjectStore];
[responseMapping addAttributeMappingsFromDictionary:#{
#"comment_id": #"commentId"
}];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:responseMapping
method:RKRequestMethodAny
pathPattern:COMMENT
keyPath:nil
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
Whats the best way to do this?
Just use a plain RKObjectMapping to a custom class or an NSDictionary and with the single status key. Then you should get a simple single item in the mapping result.
Related
I'll try to explain how I want the mapping done:
TOP lvl json object contains Players object which is an array of Player objects
each Player object contains an array, I want each of those objects in the array to be of an Event object (custom object).
now since I have a mapping of the Player object and i'm getting the array filled, tho instead of Event objects(which is what I want), i'm getting NSDictionary objects. thing is that I do have a mapping of my Event class. my issue is getting the RestKit to map these into the array.
I've tried adding responseDescriptors of an Event class tho i've had no luck.
Here is the Player object mapping
RKObjectMapping* playerMapping = [RKObjectMapping mappingForClass:[Player class]];
[playerMapping addAttributeMappingsFromDictionary:#{
...more here
#"activeEvents" : #"activeEvents"
}];
here is the request method
NSURL *taskURL = [NSURL URLWithString:kAppWebApiURLPath];
// Set object manager with base url
RKObjectManager *objectManager = [RKObjectManager sharedManager];
objectManager = [RKObjectManager managerWithBaseURL:taskURL];
objectManager.requestSerializationMIMEType = RKMIMETypeJSON;
[objectManager.HTTPClient setDefaultHeader:#"Authorization" value:kAppWebAPIKey];
[objectManager.HTTPClient setDefaultHeader:#"Content-Type" value:#"application/json"];
RKRequestDescriptor * requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:[MappingProvider inverseLoginMapping] objectClass:[LoginInfo class] rootKeyPath:nil method:RKRequestMethodPOST];
[objectManager addRequestDescriptor:requestDescriptor];
RKResponseDescriptor *playersResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:[MappingProvider playerMapping] method:RKRequestMethodGET pathPattern:nil keyPath:#"players" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptor:playersResponseDescriptor];
NSLog(#"%#",loginInfo.iOSDeviceToken);
[objectManager postObject:loginInfo path:kAppWebApiLoginPath parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult)
{}...
Update, I now need one step further of mapping, My player object contains an array of events which I successfully mapped using
[playerMapping addRelationshipMappingWithSourceKeyPath:#"activeEvents" mapping:[MappingProvider eventMapping]];
yet now each of those Event objects contains an array of Players, so its like Players -> Events -> Players.
Here is the Mapping for both Event and Player objects :
RKObjectMapping* eventMapping = [RKObjectMapping mappingForClass:[Event class]];
[eventMapping addAttributeMappingsFromDictionary:#{
#"stuffhere" : #"stuffz"
}];
RKObjectMapping* playerMapping = [RKObjectMapping mappingForClass:[Player class]];
[playerMapping addAttributeMappingsFromDictionary:#{
#"name": #"name",
#"activeEvents" : #"activeEvents"
}];
[eventMapping addRelationshipMappingWithSourceKeyPath:#"activeEvents/players" mapping:playerMapping];
now I don't get a recursive function, but how do I state in code to make that relationship
mapping of the json array to assign to my local array property ?
Remove #"activeEvents" : #"activeEvents" from the mapping and replace it with:
[playerMapping addRelationshipMappingWithSourceKeyPath:#"activeEvents" mapping:eventMapping];
You should also only have one response descriptor because the data is nested.
I have the following JSON returned from my restkit call:
{"test":{"123423":{"id":"123423","type":"mood","stress":null}}}
and I am using the following mapping
RKObjectMapping *testResponseMapping = [RKObjectMapping mappingForClass:[TestDataResponse class]];
[testResponseMapping addAttributeMappingToKeyOfRepresentationFromAttribute:#"itemNumber"];
[testResponseMapping addAttributeMappingsFromDictionary:#{
#"(itemNumber).id":#"id",
#"(itemNumber).type":#"type",
#"(itemNumber).stress":#"stress"
}];
RKResponseDescriptor *testResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:testResponseMapping method:RKRequestMethodAny pathPattern:nil keyPath:#"test" statusCodes:[NSIndexSet indexSetWithIndex:200]];
This is not quite right as I'm not sure I am handling the first "123423" (which is a number that changes) correctly.
How do I update my code to accommodate this properly? Thanks!
I have used common RKObjectManager used for different entity mapping as the following below cod but when i try to make mapping for specific entity couldn't because i have two entity with same keyPath this the problem how i can figured.
// Search mapping ...
RKEntityMapping *searchEntityMapping = [RKEntityMapping mappingForEntityForName:NSStringFromClass([ABB class]) inManagedObjectStore: aBBManager.managedObjectStore];
[searchInfoEntityMapping addAttributeMappingsFromDictionary:#{
#"count" : #"count",
#"total_count" : #"totalCount",
}];
// Search Advanced mapping ...
RKEntityMapping *searchAdvEntityMapping = [RKEntityMapping mappingForEntityForName:NSStringFromClass([ABB class]) inManagedObjectStore: aBBManager.managedObjectStore];
[searchAdvEntityMapping addAttributeMappingsFromDictionary:#{
#"count" : #"count",
#"data" : #"dataCount",
}];
// Search Descriptor
RKResponseDescriptor *aBBResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:searchEntityMapping pathPattern:nil keyPath:#"locations" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
// Search Adv Descriptor
RKResponseDescriptor *aBB2ResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:searchAdvEntityMapping pathPattern:nil keyPath:#"locations" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
You should use the pathPattern parameter to allow RestKit to know which response descriptor to use when you make a particular request (because you should be using different paths in the URLs for different entities).
If for some reason you can't, you would need to create multiple instances of RKObjectManager and use the appropriate one for each different request that you make.
I'm trying to use RestKit to map some JSON to my Core Data entities.
I have a Case entity with a caseId attribute and an optional one-to-many relationship to a Binder entity called binders. The Binder entity has an inverse one-to-one relationship to Case called case that's not optional.
I can successfully map the Case entities, but I'm having trouble with mapping the Binder entities.
My mappings are set up as follows:
RKEntityMapping *caseEntityMapping = [RKEntityMapping mappingForEntityForName:#"Case" inManagedObjectStore:managedObjectStore];
[caseEntityMapping addAttributeMappingsFromArray:[#"caseId"]];
RKEntityMapping *binderEntityMapping = [RKEntityMapping mappingForEntityForName:#"Binder" inManagedObjectStore:managedObjectStore];
NSString *pathPattern = #"rest/case/list";
[router.routeSet addRoute:[RKRoute routeWithName:#"getCases" pathPattern:pathPattern method:RKRequestMethodGET]];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:caseEntityMapping pathPattern:pathPattern keyPath:#"data" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[_objectManager addResponseDescriptor:responseDescriptor];
pathPattern = #"rest/binder/list/:caseId";
[router.routeSet addRoute:[RKRoute routeWithRelationshipName:#"binders" objectClass:[PFCase class] pathPattern:pathPattern method:RKRequestMethodGET]];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:binderEntityMapping pathPattern:pathPattern keyPath:#"data" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[_objectManager addResponseDescriptor:responseDescriptor];
I get the cases by using [_objectManager getObjectsAtPathForRouteNamed:#"getCases" object:nil parameters:nil success:… failure:…] and then inside the success block, I get the binders for each case by executing the request operation created using [_objectManager requestWithPathForRelationship:#"binders" ofObject:mappedCase method:RKRequestMethodGET parameters:nil].
But there are no mapping results for the binders. Am I missing something?
I had to add a foreign key RKConnectionDescription to the binder entity mapping, which required me to create a new attribute for the Binder entity called caseId.
Is there any way to do this without having to create a new attribute? Also, what is the key path RKConnectionDescription for/when would it be needed?
I use RESTKit successfully to access a Web service. But I have problems to map server errors (like 404, 403...) to RESTKit's standard RKErrorMessage class. Let's say I get the following JSON response from my service together with a 403 status code:
{"errors":{"message":"Some error message"}}
In my iOS application I try to map the errors with the help of:
RKObjectMapping *errorMapping = [RKObjectMapping mappingForClass:[RKErrorMessage class
[errorMapping addPropertyMapping:[RKAttributeMapping
attributeMappingFromKeyPath:#"message" toKeyPath:#"message"]];
statusCodes4xx = RKStatusCodeIndexSetForClass(RKStatusCodeClassClientError);
errorDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:notecardMapping
pathPattern:nil keyPath:#"errors" statusCodes:statusCodes4xx];
But all I get is an error from RESTKit:
Failed mapping operation: No mappable values found for any of the attributes or relationship mappings
Where is my fault? Is it just a wrong path in the descriptor for example?
You seem to be using notecardMapping instead of errorMapping in your response descriptor. Try this:
RKObjectMapping *errorMapping = [RKObjectMapping mappingForClass:[RKErrorMessage class]];
[errorMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:nil toKeyPath:#"errorMessage"]];
RKResponseDescriptor *errorDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:errorMapping
pathPattern:nil
keyPath:#"errors.message"
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassClientError)];
[manager addResponseDescriptorsFromArray:#[errorDescriptor]];