Restkit object mapping - ios

I'm struggling trying to map the following json response:
{
"data":
{
"plans":
[
{
"planid":"10",
"plandescription":"foo",
"plantype":"2",
"planvalue":"30",
"status":"Active"
}
]
}
}
This is what I'm trying to do:
RKObjectMapping *planMapping = [RKObjectMapping mappingForClass:[Plans class]];
[planMapping addAttributeMappingsFromDictionary:#{
#"planid": #"planId",
#"plandescription": #"planDescription",
#"plantype": #"planType",
#"planvalue": #"planValue",
#"status" : #"status"
}];
RKResponseDescriptor *planResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:planMapping pathPattern:nil keyPath:#"data/plans" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptor:planResponseDescriptor];
Yet the object doesn't get mapped :\ What is wrong?

Try changing keyPath:#"data/plans" to keyPath:#"data.plans"

Related

mapping with restkit " how to use multiple mapping and descriptor

Hello friends in stackoverflow:
I am having problem mapping data from the api using restkit.I really want to know where my mistake is.
Json format:
{
data: {
-current_condition: [1]
0: {
cloudcover: "16"
humidity: "59"
- weatherDesc: [1]
0: {
value: "Clear"
}
- weather: [5]
0: {
tempMinC: "10"
tempMinF: "50"
weatherCode: "119"
- weatherDesc: [1]
0: {
value: "Cloudy"
}
.......
}
here is my code how to do the mapping (I tried to mapping the 'cloudcover,humidity',and both 'weatherDesc' in current_condition and weather)
-(void)configureRestKit{
NSURL *baseURL = [NSURL URLWithString:#"http://www.raywenderlich.com"];
AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:baseURL];
RKObjectManager *objectManager = [[RKObjectManager alloc] initWithHTTPClient:client];
RKObjectMapping *currentMapping = [RKObjectMapping mappingForClass:[CurrentCondition class]];
[currentMapping addAttributeMappingsFromArray:#[#"cloudcover",#"humidity",#"weatherDesc"]];
[currentMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"current_condition" toKeyPath:#"current_condition" withMapping:currentMapping]];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:currentMapping method:RKRequestMethodGET pathPattern:#"/demos/weather_sample/weather.php" keyPath:#"data.current_condition" statusCodes:[NSIndexSet indexSetWithIndex:200]];
[objectManager addResponseDescriptor:responseDescriptor];
//weahter Desc
RKObjectMapping *weatherMapping = [RKObjectMapping mappingForClass:[Weather class]];
[weatherMapping addAttributeMappingsFromDictionary:#{#"weatherDesc": #"myweatherDesc"}];
[weatherMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"weather" toKeyPath:#"weather" withMapping:weatherMapping]];
RKResponseDescriptor *weatherresponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:weatherMapping method:RKRequestMethodGET pathPattern:#"/demos/weather_sample/weather.php" keyPath:#"data.weather" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptor:weatherresponseDescriptor];
}
-(void)loadCurrentCondition{
NSDictionary *queryParams = #{#"format": #"json"};
[[RKObjectManager sharedManager] getObjectsAtPath:#"/demos/weather_sample/weather.php" parameters:queryParams success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
_myArr = mappingResult.array;
[self Humidity];
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#"The error is :%#",error);
}];
}
-(void)Humidity{
restkitCurrentCondition *rkCC = [_myArr objectAtIndex:0];
NSLog(#"///////////////////////the humidity is: %ld",rkCC.humidity.longValue);
NSLog(#"//////////////////// the cloudcover is: %ld",rkCC.cloudcover.longValue);
NSLog(#"/////////////// the weatherDesc is %#",rkCC.weatherDesc[0][#"value"]);
NSLog(#"///////// the weatherDesc in weather is %#",rkCC.restkitweather.myweatherDesc[0][#"value"]);
NSLog(#"///////// the weatherDesc in weather is %#",rkCC.restkitweather.myweatherDesc);
}
here is what I get:
2014-07-16 14:21:36.076 myRestSample[3783:60b] I restkit:RKLog.m:33 RestKit logging initialized...
2014-07-16 14:21:36.154 myRestSample[3783:60b] I
restkit.network:RKObjectRequestOperation.m:150 GET
'http://www.raywenderlich.com/demos/weather_sample/weather.php?format=json'
2014-07-16 14:21:36.289 myRestSample[3783:3a0f] I
restkit.network:RKObjectRequestOperation.m:220 GET
'http://www.raywenderlich.com/demos/weather_sample/weather.php?format=json' (200 OK / 6
objects) [request=0.1323s mapping=0.0024s total=0.1525s]
2014-07-16 14:21:36.289 myRestSample[3783:60b] -[Weather humidity]: unrecognized
selector sent to instance 0x8f8eb30
I tried to change the descritor's keypath to 'nil',looks like this
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:currentMapping
method:RKRequestMethodGET
pathPattern:#"/demos/weather_sample/weather.php" keyPath:nil
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
The Weather and CurrentCondition are NSObject and there are four properties in CurrentCondition(cloudcover,humidity, NSArray *weaterDesc,Weather *restkitweather).There are only two properties in Weather.h (NSArray *myweatherDesc,*weatherDesc)
It seems I have already got 6 objects but why I got '[Weather humidity] Unreconized'.
Can anyone help??please..
'[Weather humidity] Unreconized'
This means that you have a Weather Instance, but you are treating it as a current conditions instance.
As per my answer to your other question you should not be using _myArr = mappingResult.array; because you can't be sure what the array contains. Instead you should be using the dictionary and extracting the correct type of object for your needs based on the key path.

Processing RestKit Response to get params not in entity

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.

RestKit RKObjectMapping issues

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!

RestKit Pagination

I'm stuck with a pagination issue.
When I go to /?PageSize=:perPage&Page=:page" I will get a json response like this:
Which I would like to map using the following paginator:
/* BBActivityPaginator */
RKObjectMapping *activityPaginationMapping = [RKObjectMapping mappingForClass:[BBActivityPaginator class]];
[activityPaginationMapping addAttributeMappingsFromDictionary:#{
#"Page" :#"currentPage",
#"PageSize" :#"perPage",
#"TotalResultCount" :#"objectCount"
}];
[activityPaginationMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"PagedListItems" toKeyPath:#"activities" withMapping:activityMapping]];
[manager addResponseDescriptor:[RKResponseDescriptor responseDescriptorWithMapping:activityPaginationMapping
pathPattern:#"/?PageSize=:perPage&Page=:page"
keyPath:#"Model.Activities"
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)]];
which is related to this mapping:
/* BBActivity */
RKObjectMapping *activityMapping = [RKObjectMapping mappingForClass:[BBActivity class]];
[activityMapping addAttributeMappingsFromDictionary:#{
#"Id" :#"identifier",
#"CreatedDateTime" :#"createdOn",
#"Description" :#"description",
#"CreatedDateTimeOrder" :#"order",
#"Type" :#"type",
#"DeletedActivityItem.Message" :#"deleted"
}];
[activityMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"User" toKeyPath:#"user" withMapping:userMapping]];
[activityMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"ObservationAdded.Observation" toKeyPath:#"observation" withMapping:observationMapping]];
[activityMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"SightingNoteAdded.SightingNote" toKeyPath:#"observationNote" withMapping:observationNoteMapping]];
[activityMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"SightingNoteAdded.Sighting" toKeyPath:#"observationNoteObservation" withMapping:observationMapping]];
[activityMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"IdentificationAdded.Sighting" toKeyPath:#"identificationObservation" withMapping:observationMapping]];
[activityMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"IdentificationAdded.Identification" toKeyPath:#"identification" withMapping:identificationMapping]];
[activityMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"PostAdded.Post" toKeyPath:#"post" withMapping:postMapping]];
[manager addResponseDescriptor:[RKResponseDescriptor responseDescriptorWithMapping:activityMapping
pathPattern:nil
keyPath:nil
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)]];
... For brevity I won't add all the mappings...
When I want to make my call to the paginator, I'm wiring up this:
-(void)setPaginatorForStream:(NSString*)streamName {
[BBLog Log:#"BBStreamController.setPaginatorForStream:"];
[BBLog Debug:#"streamName:" withMessage:streamName];
__weak typeof(self) weakSelf = self;
NSString *streamUrl = [NSString stringWithFormat:#"http://api.blahblah.org.au/%#?PageSize=:perPage&Page=:currentPage&X-Requested-With=XMLHttpRequest", streamName];
if (!self.paginator) {
paginationMapping = [RKObjectMapping mappingForClass:[BBActivityPaginator class]];
RKResponseDescriptor *activitiesResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:[RKObjectMapping mappingForClass:[BBActivityPaginator class]]
pathPattern:nil
keyPath:nil
statusCodes:[NSIndexSet indexSetWithIndex:200]];
self.paginator = [[BBActivityPaginator alloc]initWithRequest:[NSURLRequest requestWithURL:[[NSURL alloc]initWithString:streamUrl]]
paginationMapping:paginationMapping
responseDescriptors:[[NSArray alloc]initWithObjects:activitiesResponseDescriptor, nil]
andDelegate:weakSelf];
}
self.paginator.perPage = 20;
[self.paginator setCompletionBlockWithSuccess:^(RKPaginator *paginator, NSArray *objects, NSUInteger page) {
[weakSelf.tableItems addObjectsFromArray:objects];
[weakSelf.tableView reloadData];
} failure:^(RKPaginator *paginator, NSError *error) {
NSLog(#"Failure: %#", error);
}];
Which is being activated in this method:
-(void)loadRequest {
[BBLog Log:#"BBStreamController.loadRequest"];
self.fetchBatch++;
[self.paginator loadPage:self.fetchBatch];
//[self.paginator setPaginatorLoading:YES];
self.loading = YES;
}
from the class initialisation:
-(BBStreamController*)initWithGroup:(NSString*)groupIdentifier
andDelegate:(id<BBStreamProtocol>)delegate {
[BBLog Log:#"BBStreamController.initWithGroup:andDelegate:"];
self = [self init];
if(self) {
_controller = delegate;
groupId = groupIdentifier;
[self setPaginatorForStream:groupIdentifier];
[self loadRequest];
}
[self loadView];
return self;
}
And getting nothing but pain...
Output:
E restkit:RKPaginator.m:207 Paginator didn't map info to compute page count. Assuming no pages.
2013-05-06 17:48:09.487 BowerBird[26570:5807] W restkit.object_mapping:RKMapperOperation.m:98 Adding mapping error: No mappable values found for any of the attributes or relationship mappings
Any one familiar with the finer details of RestKit 0.2.x's new pagination?
Your pathPattern and keyPath information needs to be set on the activitiesResponseDescriptor definition, not some paginator response descriptor that isn't actually used for anything.
The response descriptor is for the overall response and describes how to:
Tell that we have a match : pathPattern
Find the data to process : keyPath
Create the response objects : data mapping
The paginator mapping is additional to this and is only used to extract the page data from the response being processed.
Move the path pattern and key path to the response descriptor used for the request. The path pattern should also contain "PagedListItems" by the looks of it.

Mapping server errors with RESTKit

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]];

Resources