Multi root with a GET request - ios

I am searching a way to map 2 different arrays with the following JSON
"establishments": [
{
"id": 1,
"name": "Boudin Sourdough Bakery and Cafe",
"address": "1 Stockton St",
"zip_code": "94108",
"city": "San Francisco",
"country": "us",
"phone_number": "",
"position": {
"latitude": 37.78590500000001,
"longitude": -122.406289
},
"distance_from": 13.75783097391759
}
],
"places": [
{
"id": 3,
"name": "Private Place",
"position": {
"latitude": 37.78583400000001,
"longitude": -122.406417
},
"is_private": false,
"distance_from": 0
}
]
I have 2 different mappings. One for establishment and another for place. I found some help with the documentation but it's working only for PUT or POST requests.
Currently, I have the following request
[session.objectManager getObjectsAtPathForRouteNamed:APICallSearchSearchPlaceRouteName object:nil parameters:params success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSArray * resultPlaces=mappingResult.array;
[delegate APICallDidSearch:resultPlaces];
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSError* myError=[self catchCustomErrorInRKError:error setDomain:#"Search"];
if (myError.code == NSURLErrorCancelled) return;
[delegate APICallDidFailSearch:myError];
}];
Mapping & Mapping Descriptor
RKEntityMapping *establishmentMapping = [APICallEstablishment RKGetEstablishmentMappingForManagedObjectStore:self.appDelegate.managedObjectStore];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:establishmentMapping
method:RKRequestMethodGET
pathPattern:APICallSearchSearchPlacePattern
keyPath:#"establishments"
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[session.objectManager addResponseDescriptor:responseDescriptor];
I tried to adapt the example to my case with that (just before my request written above)
RKManagedObjectRequestOperation *operation = [session.objectManager appropriateObjectRequestOperationWithObject:establishmentMapping method:RKRequestMethodGET path:#"/whatever" parameters:nil];
operation.targetObject = nil;
//Does it still exist ? (XCode says an error)
//operation.targetObjectID = nil;
[session.objectManager enqueueObjectRequestOperation:operation];
Thank you in advance for your help.

Using session.objectManager getObjectsAtPathForRouteNamed... is a good option (better than trying to use RKManagedObjectRequestOperation directly).
You need to create another response descriptor, like responseDescriptor, but for places key path and mapping.

Related

RestKit error mapping Expedia API

I am having an error when trying to map deeply nested objects from JSON with RestKit. First, I try to map hotel name which works normally. However, when I try to get price from "ChargeableRateInfo" from JSON I get following error:
restkit.object_mapping:RKMappingOperation.m:652 WARNING: Failed
mapping nested object: (null)
Here is JSON example which I am trying to map:
{
"HotelListResponse": {
"customerSessionId": "0ABAAA3E-7637-1591-4F62-5548AC792D42",
"numberOfRoomsRequested": 1,
"moreResultsAvailable": true,
"cacheKey": "-48763715:14f65548ac7:2d4e",
"cacheLocation": "10.186.170.62:7300",
"cachedSupplierResponse": {
"#supplierCacheTolerance": "NOT_SUPPORTED",
"#cachedTime": "0",
"#supplierRequestNum": "235",
"#supplierResponseNum": "1",
"#supplierResponseTime": "503",
"#candidatePreptime": "30",
"#otherOverheadTime": "5",
"#tpidUsed": "5001",
"#matchedCurrency": "true",
"#matchedLocale": "true"
},
"HotelList": {
"#size": "1",
"#activePropertyCount": "235",
"HotelSummary": {
"#order": "0",
"#ubsScore": "1069912",
"hotelId": 206005,
"name": "Mediterranean Inn",
"address1": "425 Queen Anne Ave N",
"city": "Seattle",
"stateProvinceCode": "WA",
"postalCode": 98109,
"countryCode": "US",
"airportCode": "SEA",
"supplierType": "E",
"propertyCategory": 1,
"hotelRating": 3,
"confidenceRating": 70,
"amenityMask": 7799051,
"tripAdvisorRating": 4,
"tripAdvisorReviewCount": 1086,
"tripAdvisorRatingUrl": "http://www.tripadvisor.com/img/cdsi/img2/ratings/traveler/4.0-12345-4.gif",
"locationDescription": "Near Pacific Northwest Ballet",
"shortDescription": "<p><b>Property Location</b> <br />With a stay at Mediterranean Inn, you&apos;ll be centrally located in Seattle, steps from Key Arena and minutes from Seattle Children&apos;s Theatre. This family-friendly",
"highRate": 270,
"lowRate": 162,
"rateCurrencyCode": "USD",
"latitude": 47.62244,
"longitude": -122.35672,
"proximityDistance": 12.288694,
"proximityUnit": "MI",
"hotelInDestination": true,
"thumbNailUrl": "/hotels/1000000/900000/897600/897598/897598_108_t.jpg",
"deepLink": "http://www.travelnow.com/templates/55505/hotels/206005/overview?lang=en&currency=USD&standardCheckin=9/15/2015&standardCheckout=9/17/2015&roomsCount=1&rooms[0].adultsCount=2",
"RoomRateDetailsList": {
"RoomRateDetails": {
"roomTypeCode": 15567,
"rateCode": 15567,
"maxRoomOccupancy": 2,
"quotedRoomOccupancy": 2,
"minGuestAge": 0,
"roomDescription": "Petite Room, 1 Queen Bed, Kitchenette",
"propertyAvailable": true,
"propertyRestricted": false,
"expediaPropertyId": 897598,
"RateInfos": {
"#size": "1",
"RateInfo": {
"#priceBreakdown": "true",
"#promo": "true",
"#rateChange": "false",
"RoomGroup": {
"Room": {
"numberOfAdults": 2,
"numberOfChildren": 0,
"rateKey": "81423e04-b223-4ea1-807a-8812c13b31be",
"ChargeableNightlyRates": [
{
"#baseRate": "270.00",
"#rate": "162.00",
"#promo": "true"
}, {
"#baseRate": "270.00",
"#rate": "162.00",
"#promo": "true"
}
]
}
},
"ChargeableRateInfo": {
"#averageBaseRate": "270.00",
"#averageRate": "162.00",
"#commissionableUsdTotal": "324.00",
"#currencyCode": "USD",
"#maxNightlyRate": "162.00",
"#nightlyRateTotal": "324.00",
"#grossProfitOffline": "54.87",
"#grossProfitOnline": "81.40",
"#surchargeTotal": "69.07",
"#total": "393.07",
"NightlyRatesPerRoom": {
"#size": "2",
"NightlyRate": [
{
"#baseRate": "270.00",
"#rate": "162.00",
"#promo": "true"
}, {
"#baseRate": "270.00",
"#rate": "162.00",
"#promo": "true"
}
]
},
"Surcharges": {
"#size": "1",
"Surcharge": {
"#type": "TaxAndServiceFee",
"#amount": "69.07"
}
}
},
"nonRefundable": false,
"rateType": "MerchantStandard",
"promoId": 212134483,
"promoDescription": "24 hour deal: save 40%",
"promoType": "Standard",
"currentAllotment": 3
}
}
}
}
}
}
}
}
And here is my code where I try to map this JSON:
- (void)configureRestKit
{
// initialize AFNetworking HTTPClient
NSURL *baseURL = [NSURL URLWithString:#"http://api.ean.com"];
AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:baseURL];
// initialize RestKit
RKObjectManager *objectManager = [[RKObjectManager alloc] initWithHTTPClient:client];
// setup object mappings
RKObjectMapping *hotelMapping = [RKObjectMapping mappingForClass:[HotelList class]];
[hotelMapping addAttributeMappingsFromArray:#[#"name"]];
RKObjectMapping *priceMapping = [RKObjectMapping mappingForClass:[ChargeableRateInfo class]];
[priceMapping addAttributeMappingsFromDictionary:#{#"total": #"total"}];
[hotelMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"RoomRateDetailsList.RoomRateDetails.RateInfos.RateInfo.ChargeableRateInfo" toKeyPath:#"chargeableRateInfo" withMapping:priceMapping]];
// register mappings with the provider using a response descriptor
RKResponseDescriptor *responseDescriptor =
[RKResponseDescriptor responseDescriptorWithMapping:hotelMapping
method:RKRequestMethodGET
pathPattern:#"/ean-services/rs/hotel/v3/list"
keyPath:#"HotelListResponse.HotelList.HotelSummary"
statusCodes:[NSIndexSet indexSetWithIndex:200]];
[objectManager addResponseDescriptor:responseDescriptor];
}
Does anyone know how to solve this? Thanks
The mapping key should be #total based on the content in the JSON.
This isn't ideal however as # is a special character in KVC which RestKit uses heavily. You will need to work around this with something from this answer or this pull request.

POST raw json code ios

i'm new to ios developing and i want to ask how can i post a raw json code to the server.
For Example: i want to send this JSON raw data to http://example.com/user
{
"user":
{
"username": "jkaaannyaad11",
"password": "secret123456",
"gender": "male",
"first_name": "assd",
"last_name": "ffsasd",
"birth_date": "can be null",
"phone_number": "12343234",
"have_car":"1",
"same_gender" :"0",
"uid": "this is id for facebook , can be null"
},
"home":
{
"longitude": "31.380301",
"latitude": "30.054272",
"name": "city"
},
"work":
{
"longitude": "30.068237",
"latitude": "31.024275",
"name": "village"
},
"email":
{
"email_type": "work",
"email": "hello.me#me.com"
}
}
so how can i do it ?
For Example in Android using the JSONObject i can easily oraganize them and then POST them to the website
JSONObject obj = new JSONObject();
JSONObject userObj = new JSONObject();
JSONObject homeObj = new JSONObject();
JSONObject workObj = new JSONObject();
JSONObject emailObj = new JSONObject();
try {
obj.put("user", userObj);
obj.put("home", homeObj);
obj.put("work", workObj);
obj.put("email", emailObj);
homeObj.put("longitude", homePlace.LocationRef.Lng);
homeObj.put("latitude", homePlace.LocationRef.Lat);
homeObj.put("name", homePlace.LocationRef.Address);
Use the AFNetworking library. On the repository page there are many examples including the one below to make a POST request.
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *parameters = #{#"foo": #"bar"};
[manager POST:#"http://example.com/resources.json" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];

How to map this object in RESTKit

I have JSON of following kind
{
"Client": {
"FirstName": "String",
"LastName": "String",
"Email": "String",
"Password": "String",
"PhoneNumber": "String",
"Token": "String"
},
"ErrorMessage": "String",
"FriendlyMessage": "String"
}
I know that while mapping if I specify a key path then RestKit matches fields from object specified, in this case Client, to the code I am using for that is as follows
[responseMapping addAttributeMappingsFromDictionary:#{
#"FirstName": #"FirstName",
#"LastName": #"LastName",
#"Email": #"Email",
#"PhoneNumber": #"PhoneNumber",
#"Token": #"Token",
#"Password": #"Password",
#"ErrorMessage": #"ErrorMessage"}];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:responseMapping
method:RKRequestMethodPOST
pathPattern:nil
keyPath:#"Client"
statusCodes:[NSIndexSet indexSetWithIndex:200]];
But I have two additional fields to map which aren't under client object. How do I map ErrorMessage and FriendlyMessage fields ?
Generally you wouldn't want to map them into your client object, you would want to map them into some other object. You would usually use a different object and response mapping, where the response mapping uses a different key path.
If for some reason you did want them in the same object then you could look at using the #metadata / #parent to get to the parent (https://github.com/RestKit/RestKit/pull/1435).

How to pass an array in an url query parameter using nsurl in objective-c?

The API need to pass an array in an url query parameter, how to acheive this in iOS?
I only know how to pass a single vaue, like the API below : ?title=Design Milk&id=feed/http://feeds.feedburner.com/design-milk
API sample:
"title": "Design Milk",
"id": "feed/http://feeds.feedburner.com/design-milk",
"categories": [
{
"id": "user/c805fcbf-3acf-4302-a97e-d82f9d7c897f/category/design",
"label": "design"
},
{
"id": "user/c805fcbf-3acf-4302-a97e-d82f9d7c897f/category/weekly",
"label": "weekly"
},
{
"id": "user/c805fcbf-3acf-4302-a97e-d82f9d7c897f/category/global.must",
"label": "must reads"
}
]
Create a collection and then use NSJSONSerialization to create JSON data representation. Use the resulting data as the POST data.
NSDictionary *parameters = #{
#"title": #"Design Milk",
#"id": #"feed/http://feeds.feedburner.com/design-milk",
#"categories": #[
#{
#"id": #"user/c805fcbf-3acf-4302-a97e-d82f9d7c897f/category/design",
#"label": #"design"
},
#{
#"id": #"user/c805fcbf-3acf-4302-a97e-d82f9d7c897f/category/weekly",
#"label": #"weekly"
},
#{
#"id": #"user/c805fcbf-3acf-4302-a97e-d82f9d7c897f/category/global.must",
#"label": #"must reads"
}
]
};
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictData options:0 error:&error];

RestKit Core Data mapping one to many

I am using RestKit to map the following JSON to core data.
This is my model:
this is my methods:
RKEntityMapping *userMapping = [RKEntityMapping mappingForEntityForName:NSStringFromClass([User class]) inManagedObjectStore:managedObjectStore];
userMapping.identificationAttributes = #[#"id"];
[userMapping addAttributeMappingsFromDictionary:#{
#"birthday":#"birthday",
#"email":#"email",
#"facebook_token":#"facebook_token",
#"first_name":#"first_name",
#"gender":#"gender",
#"interested_in":#"interested_in",
#"last_name":#"last_name",
#"password":#"password",
#"m8_status":#"m8_status",
#"status":#"status",
#"languages": #"languages",
#"hometown":#"hometown",
#"location":#"location",
#"avatar_url":#"avatar_url",
#"mood":#"mood"
}];
RKEntityMapping *findUserMapping = [RKEntityMapping mappingForEntityForName:NSStringFromClass([FindUser class]) inManagedObjectStore:managedObjectStore];
findUserMapping.identificationAttributes = #[#"id"];
[findUserMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"users" toKeyPath:#"users" withMapping:userMapping]];
[manager addResponseDescriptorsFromArray:#[
[RKResponseDescriptor responseDescriptorWithMapping:findUserMapping
pathPattern:#"/v1/users"
keyPath:nil statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)]
]];
This is getting objects from example JSON:
{
"users": [
{
"avatar_url": null,
"birthday": "04/11/1984",
"email": "antonina.duminskaya#wildermancruickshank.co.uk", "first_name": "Antonina",
"gender": "female",
"hometown": null,
"id": "5264ee384d61632c4b2f0000",
"interested_in": [
"male",
"female" ],
"languages": [], "last_name": "Duminskaya", "location": null, "m8_status": null,
"mood": null,
"status": null
} ]
}
here:
[objectManager getObjectsAtPath:#"/v1/users" parameters:#{#"session_id":session.id} success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
FindUser *findUsers = [[self.fetchedFindUsersResultsController fetchedObjects] lastObject];
NSLog(#"%#", findUsers.users);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
}];
I have message in log:
Relationship 'users' fault on managed object (0x8e964a0) <FindUser: 0x8e964a0> (entity: FindUser; id: 0x8da0790 <x-coredata://083BB731-FDD7-4A35-A174-724F50862A02/FindUser/p1> ; data: {
id = nil;
users = "<relationship fault: 0x8deb260 'users'>";
})
And In mappingResults I have all results about json
Core Data is representing the relationship initially as fault saving memory by not loading all the object graph at once.
https://developer.apple.com/library/ios/documentation/cocoa/conceptual/CoreData/Articles/cdFaultingUniquing.html
Also, do not use the reserved word 'id' as the Restkit identification attribute for your managed objects. Try using findUserId and userId and update your mappings accordingly.

Resources