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...
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'm totally new to RestKit and am struggling somewhat.
JSON:
{
"teams": [
{
"id": 1,
"name": "Team A"
},
{
"id": 2,
"name": "Team B"
}
],
"users": [
{
"id": 1,
"name": "cameron",
"teamId": 1
},
{
"id": 2,
"name": "paul",
"teamId": 2
}
]
}
CoreData:
#interface Team : NSManagedObject
#property (nonatomic, retain) NSNumber * teamId;
#property (nonatomic, retain) NSString * name;
#end
#interface User : NSManagedObject
#property (nonatomic, retain) NSNumber * userId;
#property (nonatomic, retain) NSString * name;
#property (nonatomic, retain) Team * team;
#end
My application logic looks like this:
// team mapping
RKEntityMapping *teamMapping = [RKEntityMapping mappingForEntityForName:#"Team" inManagedObjectStore:[RKManagedObjectStore defaultStore]];
teamMapping.identificationAttributes = #[#"teamId"];
[teamMapping addAttributeMappingsFromDictionary:#{
#"id": #"teamId",
#"name": #"name"
}];
// Register our mappings with the provider
RKResponseDescriptor *teamResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:teamMapping
pathPattern:nil
keyPath:#"teams"
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[self.objectManager addResponseDescriptor:teamResponseDescriptor];
// user mapping
RKEntityMapping *userMapping = [RKEntityMapping mappingForEntityForName:#"User" inManagedObjectStore:[RKManagedObjectStore defaultStore]];
userMapping.identificationAttributes = #[#"userId"];
[userMapping addAttributeMappingsFromDictionary:#{
#"id": #"userId",
#"name": #"name"
}];
// Register our mappings with the provider
RKResponseDescriptor *userResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:userMapping
pathPattern:nil
keyPath:#"users"
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[self.objectManager addResponseDescriptor:userResponseDescriptor];
I can't for the life of me work out how to get RestKit to populate the team Property of the user objects.
I've look at so many posts but nothing I try works, is this not a usual use case?
Does anyone know how to do this, help would be very appreciated!
Thanks.
You need to add a transient attribute to your User entity which holds the associated teamId. This needs to be added to your userMapping.
Then, you need to add a relationship definition to your userMapping:
[userMapping addConnectionForRelationship:#"team" connectedBy:#{ #"teamId": #"teamId" }];
This gives RestKit the information it needs to make the connection and instructs it to make the connection as part of the mapping operation.
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 totally new to RestKit and am struggling somewhat.
JSON:
{
"teams": [
{
"id": 1,
"name": "Team A"
},
{
"id": 2,
"name": "Team B"
}
],
"users": [
{
"id": 1,
"name": "cameron",
"teamId": 1
},
{
"id": 2,
"name": "paul",
"teamId": 2
}
]
}
CoreData:
#interface Team : NSManagedObject
#property (nonatomic, retain) NSNumber * teamId;
#property (nonatomic, retain) NSString * name;
#end
#interface User : NSManagedObject
#property (nonatomic, retain) NSNumber * userId;
#property (nonatomic, retain) NSString * name;
#property (nonatomic, retain) Team * team;
#end
My application logic looks like this:
// team mapping
RKEntityMapping *teamMapping = [RKEntityMapping mappingForEntityForName:#"Team" inManagedObjectStore:[RKManagedObjectStore defaultStore]];
teamMapping.identificationAttributes = #[#"teamId"];
[teamMapping addAttributeMappingsFromDictionary:#{
#"id": #"teamId",
#"name": #"name"
}];
// Register our mappings with the provider
RKResponseDescriptor *teamResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:teamMapping
pathPattern:nil
keyPath:#"teams"
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[self.objectManager addResponseDescriptor:teamResponseDescriptor];
// user mapping
RKEntityMapping *userMapping = [RKEntityMapping mappingForEntityForName:#"User" inManagedObjectStore:[RKManagedObjectStore defaultStore]];
userMapping.identificationAttributes = #[#"userId"];
[userMapping addAttributeMappingsFromDictionary:#{
#"id": #"userId",
#"name": #"name"
}];
// Register our mappings with the provider
RKResponseDescriptor *userResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:userMapping
pathPattern:nil
keyPath:#"users"
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[self.objectManager addResponseDescriptor:userResponseDescriptor];
I can't for the life of me work out how to get RestKit to populate the team Property of the user objects.
I've look at so many posts but nothing I try works, is this not a usual use case?
Does anyone know how to do this, help would be very appreciated!
Thanks.
You need to add a transient attribute to your User entity which holds the associated teamId. This needs to be added to your userMapping.
Then, you need to add a relationship definition to your userMapping:
[userMapping addConnectionForRelationship:#"team" connectedBy:#{ #"teamId": #"teamId" }];
This gives RestKit the information it needs to make the connection and instructs it to make the connection as part of the mapping operation.
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.