I'm doing a GET Request with RESTKit and when I do my object mapping, it doesn't work. However, it always says that it mapped one object in the mapping result, but I don't know what that is or how I can get it to map the rest of the objects. What exactly am I doing wrong to cause the mapping result to show up as one object mapped and how do I get it to map all the proper objects?
Here is the mapping result:
Mapping Result: (
"<Info: 0x9c91130>"
)
Here is my GET Request:
//RK Logging
RKLogConfigureByName("RestKit/Network", RKLogLevelTrace);
NSIndexSet *statusCodeSet = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful);
NSString *urlString = [NSString stringWithFormat:#"https://beta.stuff.com/"];
NSURL *url = [NSURL URLWithString:urlString];
//Object Mapping
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[Info class]];
[mapping addAttributeMappingsFromDictionary:#{#"name": #"name", #"id": #"strenuusID", #"location_specialties.address": #"address", #"location_specialties.state": #"state", #"location_specialties.zip": #"zipcode", #"location_specialties.address_lines": #"address_lines"}];
NSString *pathPatternString = [NSString stringWithFormat:#"stuff/%#/stuff2/%#/", moreresultsVCSobj.projectNumber, moreresultsVCSobj.doctorStuff];
//Response Descriptor
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:mapping
method:RKRequestMethodGET
pathPattern:pathPatternString
keyPath:#""
statusCodes:statusCodeSet];
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:url];
[manager addResponseDescriptor:responseDescriptor];
[manager.HTTPClient setDefaultHeader:#"Auth-Token" value:moreresultsVCSobj.userAuthToken];
Info *info = [Info new];
[manager getObject:info path:pathPatternString parameters:nil success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult)
{
NSLog(#"Mapping Result: %#", mappingResult.array);
} failure:^(RKObjectRequestOperation *operation, NSError *error)
{
NSLog(#"Error: %#", error);
}];
Here is the JSON that I am parsing:
response.body=
{
"name": "Name, Generic N, DDS",
"id": 123456,
"npi": "1234567890",
"hospitality": false,
"groupiness": [
"Other"
],
"client_ids": null,
"has_comments": false,
"comment_count": 0,
"is_facility": false,
"location_specialties": [
{
"id": 123456,
"address_id": 454345,
"address": "1234 Rifle Rd",
"state": "Al",
"zip": "43543",
"address_lines": [
"1234 Rifle Rd",
"Generic Town, Al 43543",
"111-222- 3344"
],
"latitude": 21432234,
"longitude": 432432,
"is_validated": true,
"providers_at_address_count": 2,
"specialties": [
{
"name": "Dentists",
"plans": [
{
"name": "Plan name",
"lists_specialty": true
},
{
"name": "Plane name 2",
"lists_specialty": true
},
{
"name": "Plan name 3",
"lists_specialty": true
}
]
}
]
},
[
{
"id": 123456,
"address_id": 454345,
"address": "1234 Rifle Rd",
"state": "Al",
"zip": "43543",
"address_lines": [
"1234 Rifle Rd",
"Generic Town, Al 43543",
"111-222- 3344"
],
"latitude": 21432234,
"longitude": 432432,
"is_validated": true,
"providers_at_address_count": 2,
"specialties": [
{
"name": "Dentists",
"plans": [
{
"name": "Plan name",
"lists_specialty": true
},
{
"name": "Plane name 2",
"lists_specialty": true
},
{
"name": "Plan name 3",
"lists_specialty": true
}
]
}
]
},
"hospital_detail": null,
"tags": [
]
}
Edited: Here is my Info.h file. I tried checking the mappings other things like name but they still don't work.
#import <Foundation/Foundation.h>
#interface Info : NSObject
#property (nonatomic, copy) NSString *name;
#property (nonatomic, copy) NSString *strenuusID;
#property (nonatomic, copy) NSString *npi;
#property (nonatomic, copy) NSArray *specialty_search_groups;
#property (nonatomic, copy) NSArray *address_lines;
#property (nonatomic, copy) NSArray *address;
#property (nonatomic, copy) NSString *state;
#property (nonatomic, copy) NSString *zipcode;
#property (nonatomic, copy) NSString *planName;
#end
You get one result object because your JSON is a dictionary. Your mapping and response descriptor are written in terms of a single object.
This mapping:
#"location_specialties.address": #"address"
Won't work because location_specialties is an array so there is no way to access the address. Unless your destination is an array variable, then it could possibly work.
You need to check the contents of your Info object in detail and look for issues in your trace log. If you still have issues you need to give details on the Info object itself.
Related
How can i map this json
{
"json": [{
"json_department": [{
"department": {
"id": 1,
"inst_id": 1,
"dept_name": "Department",
"description": "test"
},
"needDelete": true
}],
"json_subjects": [{
"subjects": [{
"id": 1,
"department_id": 1,
"subject_name": "Sub 1"
}, {
"id": 2,
"department_id": 1,
"subject_name": "Sub 2"
}],
"needDelete": true
}]
}]
}
#interface class_department : NSObject
#property(nonatomic, assign) NSInteger dept_id;
#property(nonatomic, assign) NSInteger inst_id;
#property(nonatomic, strong) NSString *dept_name;
#property(nonatomic, strong) NSString *description_;
#end
_
#interface class_department_list : NSObject
#property(nonatomic, strong) class_department *department;
#property(nonatomic, assign) BOOL needDelete;
#end
-
#interface sync_json : NSObject
#property(nonatomic, strong) NSMutableArray *json_department;
#property(nonatomic, strong) NSMutableArray *json_subjects;
#end
-
-(RKResponseDescriptor *)getResponseDescriptor
{
RKObjectMapping *class_department_mapping = [RKObjectMapping mappingForClass:[class_department class]];
[class_department_mapping addAttributeMappingsFromDictionary:#{
#"id":#"dept_id",
#"inst_id":#"inst_id",
#"dept_name":#"dept_name"
#"description":#"description_",
}];
RKObjectMapping *class_department_list_mapping = [RKObjectMapping mappingForClass:[class_department_list class]];
[class_department_list_mapping addAttributeMappingsFromDictionary:#{
#"needDelete":#"needDelete"
}];
[class_department_list_mapping addPropertyMapping:[RKRelationshipMapping
relationshipMappingFromKeyPath:#"json_department.department"
toKeyPath:#"department"
withMapping:class_department_mapping]];
RKObjectMapping *json_mapping = [RKObjectMapping mappingForClass:[sync_json class]];
[json_mapping addPropertyMapping:[RKRelationshipMapping
relationshipMappingFromKeyPath:#"json_department"
toKeyPath:#"json_department"
withMapping:class_department_list_mapping]];
NSIndexSet *statusCodes = RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful);
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:json_mapping
method:RKRequestMethodGET
pathPattern:nil
keyPath:#"json"
statusCodes:statusCodes];
return responseDescriptor;
}
OKay this is code i'm using for mapping the json. i got the result for 'needDelete' but mapping to class_department is not happen. Please give me a way to done this.
Thank you.
Shinurag KR
Sorry, but try to forget this ugly implementation. Mantle do everythig pretty easy for you. Project: https://github.com/Mantle/Mantle Example: http://www.objc.at/mantle
I had a JSON response of this type:
{
"d": { "id": "1", "user": "test"}
}
which I was parsing with Restkit with the following code:
#interface ODataUser : NSObject<ODataObject>
#property (nonatomic, copy) NSString * id;
#property (nonatomic, copy) NSString * user;
-(NSString*)getId;
-(NSString*)getUser;
#end
RKObjectMapping *map = [RKObjectMapping mappingForClass:[ODataUser
class]]; [mapping addAttributeMappingsFromDictionary: #{ #"id" :
#"id", #"user" : #"user" } ];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:map method:RKRequestMethodGET pathPattern:nil keyPath:#"d" statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
However, now my response has changed to something like this:
{
"d": { "results": [ {"id": "1", "user": "test"} ] }
}
How can I reflect those changes on the response on my code?
Change your response descriptor to use:
keyPath:#"d.results"
as this will navigate into the d dictionary to get the results array and process all of the dictionaries it contains.
I have this JSON response that I can't figure out how to map. It looks like this:
{
"responseError": null,
"displayMenuList": {
"MenuList": [
{
"ID": "3223",
"Name": "Main",
"AddressURL": "www.mysite.com",
"DisplayType": "True",
"ImageURL": "main.png",
"NotSplitBUser": "True",
"ParentCategoryId": "3223",
"PrivateUser": "True",
"SortOrder": 1,
"SplitBUser": "True",
"TargetURL": "_self"
},
{
"ID": "3307",
"Name": "Contact",
"AddressURL": "www.mysite.com",
"DisplayType": "True",
"ImageURL": "service.png",
"NotSplitBUser": "True",
"ParentCategoryId": "3224",
"PrivateUser": "True",
"SortOrder": 0,
"SplitBUser": "True",
"TargetURL": "_self"
},
{
"ID": "3298",
"Name": "Call Us",
"AddressURL": "www.mysite.com",
"DisplayType": "True",
"ImageURL": "service.png",
"NotSplitBUser": "True",
"ParentCategoryId": "3224",
"PrivateUser": "True",
"SortOrder": 1,
"SplitBUser": "True",
"TargetURL": "_self"
},
{
"ID": "3224",
"Name": "Service",
"AddressURL": "www.mysite.com",
"DisplayType": "True",
"ImageURL": "service.png",
"NotSplitBUser": "True",
"ParentCategoryId": "3224",
"PrivateUser": "True",
"SortOrder": 2,
"SplitBUser": "True",
"TargetURL": "_self"
}
]
},
"responseCurrentBillState": null,
"responseGetPcrfSubBuckets": null,
"userData": {
"abroadInd": null,
"accountType": "B",
"customerId": "",
"fullName": "Juan",
"subscriberNumber": ""
}
}
I just can't figure out how to map those objects, I've created object called RKSideMenu, also an object called RKUserData they look like this:
#interface RKSideMenu : NSObject
#property (copy, nonatomic) NSString *addressURL;
#property (copy, nonatomic) NSString *displayType;
#property (copy, nonatomic) NSNumber *id_number;
#property (copy, nonatomic) NSString *imageURL;
#property (copy, nonatomic) NSString *name;
#property (assign, nonatomic) BOOL splitBUser;
+ (NSDictionary*)getAttributes;
#end
#implementation RKSideMenu
+ (NSDictionary*)getAttributes
{
return [NSDictionary dictionaryWithObjects:#[#"addressURL", #"displayType", #"id_number", #"imageURL", #"name", #"splitBUser"]
forKeys:#[#"AddressURL", #"DisplayType", #"ID", #"ImageURL", #"Name", #"SplitBUser"]];
}
#end
#interface RKUserData : NSObject
#property (copy, nonatomic) NSString *abroadInd;
#property (copy, nonatomic) NSString *accountType;
#property (copy, nonatomic) NSString *customerID;
#property (copy, nonatomic) NSString *fullName;
#property (copy, nonatomic) NSString *subscriberNumber;
+ (NSDictionary*)getAttributes;
#end
#implementation RKUserData
+ (NSDictionary*)getAttributes
{
return [NSDictionary dictionaryWithObjects:#[#"abroadInd", #"accountType", #"customerID", #"fullName;", #"subscriberNumber"]
forKeys:#[#"abroadInd", #"accountType", #"customerId", #"fullName;", #"subscriberNumber"]];
}
#end
I started mapping with those two methods, but than I stuck and don't know what to do. I look at https://github.com/RestKit/RestKit/wiki/Object-mapping, but still couldn't get it right.
RKObjectMapping *sideMenuMapping = [RKObjectMapping mappingForClass:[RKSideMenu class]];
[sideMenuMapping addAttributeMappingsFromDictionary:[RKSideMenu getAttributes]];
RKObjectMapping *userDataMapping = [RKObjectMapping mappingForClass:[RKUserData class]];
[userDataMapping addAttributeMappingsFromDictionary:[RKUserData getAttributes]];
Thanks in advance!
Edit: Json on top replaced with real json from server.
So what you need to do in order to setup your mapping is first of all define the base url of your API, like so:
AFHTTPClient *client = [AFHTTPClient clientWithBaseURL:[NSURL URLWithString:#"URL_TO_YOUR_API"]];
RKObjectManager *objectManager = [[RKObjectManager alloc] initWithHTTPClient:client];
Then you need to set a response descriptor for the url that outputs the json above:
[[RKObjectManager sharedManager] addResponseDescriptor:[RKResponseDescriptor responseDescriptorWithMapping:sideMenuMapping
method:RKRequestMethodAny
pathPattern:#"/mainScreenData"
keyPath:#"displayMenuList.MenuList"
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)]];
"RKRequestMethodAny" should be replaced by the Request Method you are using e.g. "RKRequestMethodGET".
Then you just retrieve the objects by calling:
[[RKObjectManager sharedManager] getObjectsAtPath:#"/mainScreenData"
parameters:nil
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSArray *sideMenuList = [NSMutableArray arrayWithArray:[mappingResult array]];
}
failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#"%#",[error localizedDescription]);
}];
I would highly recommend you having a look at the demos that are supplied by RestKit. That makes the whole process a lot clearer.
Cheers,
Sebastian
I'm having problems when posting to my server. Every value is being parsed expect the property-names of my array aren't.
My server is expecting something like this:
{
"location": 2,
"_id": "517808546b496658c10209",
"products": [
{
"amount": 3,
"total": 6.6,
"name": "Coke",
"price": 2.2
},{
"amount": 1,
"total": 4.0,
"name": "Water",
"price": 2
}
]
}
but my client is sending this:
{
"location": 2,
"_id": "517808546b496658c10209",
"products": [
3,
6.6,
"Coke",
2.2,
1,
4.0,
"Water",
2
]
}
Product:
#property (nonatomic) NSNumber *_id;
#property (nonatomic, strong) NSString *name;
#property (nonatomic, strong) NSString *detail;
#property (nonatomic, assign) float price;
#property (nonatomic, strong) Category *category;
#property (nonatomic, assign) int amount;
#property (nonatomic, assign) float total;
my code:
RKObjectMapping *productMapping = [RKObjectMapping requestMapping];
[productMapping addAttributeMappingsFromDictionary:#{#"productId":#"_id",#"amount":#":amount",#"total":#"total",#"price":#"price",#"name":#"name"}];
RKObjectMapping *horecaMapping = [RKObjectMapping requestMapping];
[horecaMapping addAttributeMappingsFromDictionary:#{ #"Id": #"_Id",#"deliverySpotId":#"location"}];
[horecaMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"self.getBasketSet" toKeyPath:#"products" withMapping:productMapping]];
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:horecaMapping objectClass:[Horeca class] rootKeyPath:nil];
[RKMIMETypeSerialization registerClass:[RKNSJSONSerialization class] forMIMEType:#"text/plain"];
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:baseURL];
[manager addRequestDescriptor:requestDescriptor];
[manager postObject:sharedHoreca path:#"/orders" parameters:nil success:nil failure:nil];
--update 1--
I also tried to make an NSSET of my array but this still doesn't help me.
(nsarray to nsset restkit)
The self.getBasketSet key path is giving me pause -- what is that returning? If your sharedHoreca object returns an NSArray of objects responding to the key paths specified then it should do what you are expecting...
This is the json that I need to post to services.
{
"deviceToken":"asdfasdfasdf",
"alarm": [
{
"start" "8:30",
"end": "9:30",
"line": "156",
"code": "xxxafsdfasdf",
"station": "asdfa",
"stationLeft": 5,
"available": true,
"times": 2
}]
}
The response data just have one more field "id" in alarm:
{
"deviceToken":"asdfasdfasdf",
"alarm": [
{
"id":1,
"start" "8:30",
"end": "9:30",
"line": "156",
"code": "xxxafsdfasdf",
"station": "asdfa",
"stationLeft": 5,
"available": true,
"times": 2
}]
}
Then I define two objects:
DeviceAlarm Object:
#interface DeviceAlarm : NSObject
#property(nonatomic, strong) NSMutableArray *alarm;
#property(nonatomic, copy) NSString *deviceToken;
#end
Alarm Object:
#interface Alarm : NSObject
#property(nonatomic, copy) NSNumber *id;
#property(nonatomic, copy) NSString *start;
#property(nonatomic, copy) NSString *end;
#property(nonatomic, copy) NSString *code;
#property(nonatomic, copy) NSString *line;
#property(nonatomic, copy) NSString *station;
#property(nonatomic, copy) NSNumber *stationLeft;
#property(nonatomic) BOOL available;
#property(nonatomic, copy) NSNumber *times;
#end
This is my code to post.
DeviceAlarm* devicealarm = [[DeviceAlarm alloc] init];
Alarm* alarm = [[Alarm alloc] init];
alarm.start = #"8:00";
alarm.end = #"9:30";
alarm.line = #"156";
alarm.code = #"fasdfasdf";
alarm.station = #"asdfas";
alarm.stationLeft = #1000;
alarm.available = true;
alarm.times = #1;
devicealarm.alarm = [NSArray arrayWithObjects:alarm , nil];
devicealarm.deviceToken = #"adsfasdfasdf";
RKObjectMapping *alarmMapping = [RKObjectMapping requestMapping];
[alarmMapping addAttributeMappingsFromArray:#[#"start",#"end",#"code",#"station", #"stationLeft",#"available",#"times",#"line"]];
RKObjectMapping *deviceMapping = [RKObjectMapping requestMapping];
RKRelationshipMapping *alarmRelationship = [RKRelationshipMapping
relationshipMappingFromKeyPath:#"alarm"
toKeyPath:#"alarm"
withMapping:alarmMapping];
[deviceMapping addAttributeMappingsFromArray:#[#"deviceToken"]];
[deviceMapping addPropertyMapping:alarmRelationship];
NSString* path = #"/api/alarm/asdfasdf";
RKRequestDescriptor *requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:deviceMapping
objectClass:[DeviceAlarm class]
rootKeyPath:nil];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:[DeviceAlarm DeviceAlarmResponseMapping]
pathPattern:nil
keyPath: nil
statusCodes:[NSIndexSet indexSetWithIndex:200]];
RKObjectManager *manager = [RKObjectManager managerWithBaseURL:[NSURL URLWithString:#"http://127.0.0.1:5000/"]];
[manager addRequestDescriptor:requestDescriptor];
[manager addResponseDescriptor:responseDescriptor];
[manager postObject:devicealarm path:path parameters:nil
success:^(RKObjectRequestOperation *operation, RKMappingResult *result) {
NSLog(#"Loading mapping result: %#", result);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
RKLogError(#"Operation failed with error: %#", error);
}];
Then I check the post data in services, I found restkit post an error array json.
alarm dict lost.
{
"deviceToken":"asdfasdfasdf",
"alarm": [
"8:30",
"9:30",
"156",
"xxxafsdfasdf",
"asdfa",
5,
true,
2
]
}
Please help me~ :)
LOL, I have fixed my issues, I changed the field type from "NSMutableArray" to "NSSet" in DeviceAlarm Object, and then it works. I don't know why. Hope it can help us.