I have this issue, that i'm mapping all object properly, but the properties that are inside the root object, for some reason I cannot map.
This is the JSON:
{
"responseError": null,
"responseIsRegisteredServices": {
"registeredToServiceAntiVirus": true,
"registeredToServiceCloud": true,
"registeredToServiceMusic": true,
"registeredToServiceSong": true,
"registeredToServiceTv": true
},
"responseRegisteredServicesCloud": null,
"responseRegisteredServicesMusic": [
{
"ID": null,
"Name": null,
"AlbumPic": "110_110.png",
"ArtistName": "Rihanna"
},
{
"ID": null,
"Name": null,
"AlbumPic": "110_110.png",
"ArtistName": "Rihanna"
},
{
"ID": null,
"Name": null,
"AlbumPic": "110_110.png",
"ArtistName": "Steve Angello"
}
]
}
This is the RegisteredServices class:
#interface RegisteredServices : NSObject
#property (nonatomic) ResponseError *responseError;
#property (nonatomic) NSNumber *registeredToServiceAntiVirus;
#property (nonatomic) NSNumber *registeredToServiceCloud;
#property (nonatomic) NSNumber *registeredToServiceMusic;
#property (nonatomic) NSNumber *registeredToServiceSong;
#property (nonatomic) NSNumber *registeredToServiceTv;
#property (nonatomic) CloudServices *responseRegisteredServicesCloud;
#property (nonatomic) NSArray *responseRegisteredServicesMusix;
#end
This is the 'CloudServices' class:
#interface CloudServices : NSObject
#property (nonatomic) NSString *capacityType;
#property (nonatomic) NSNumber *currentCapacity;
#property (nonatomic) NSString *lastBackupDate;
#property (nonatomic) NSNumber *percentage;
#property (nonatomic) NSNumber *totalCapacity;
#end
This is the 'MusicServices' class:
#interface MusicServices : NSObject
#property (nonatomic) NSNumber *idNum;
#property (nonatomic) NSString *name;
#property (nonatomic) NSString *albumPic;
#property (nonatomic) NSString *artistName;
#end
This is the mapping itself:
RKObjectMapping *musixMapping = [RKObjectMapping mappingForClass:[MusicServices class]];
[musicMapping addAttributeMappingsFromDictionary:#{ #"ID" : #"idNum",
#"Name" : #"name",
#"AlbumPic" : #"albumPic",
#"ArtistName" : #"artistName" }];
RKObjectMapping *cloudMapping = [RKObjectMapping mappingForClass:[CloudServices class]];
[cloudMapping addAttributeMappingsFromDictionary:#{#"capacityType": #"capacityType",
#"currentCapacity": #"currentCapacity",
#"lastBackupDate": #"lastBackupDate",
#"percentage": #"percentage",
#"totalCapacity": #"totalCapacity" }];
RKObjectMapping *registeredServicesMapping = [RKObjectMapping mappingForClass:[RegisteredServices class]];
[registeredServicesMapping addAttributeMappingsFromDictionary:#{ #"registeredToServiceAntiVirus" : #"registeredToServiceAntiVirus",
#"registeredToServiceCloud" : #"registeredToServiceCloud",
#"registeredToServiceMusic" : #"registeredToServiceMusic",
#"registeredToServiceSong" : #"registeredToServiceSong",
#"registeredToServiceTv" : #"registeredToServiceTv", }];
[registeredServicesMapping addRelationshipMappingWithSourceKeyPath:#"responseRegisteredServicesMusic" mapping:musixMapping];
[registeredServicesMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"responseError"
toKeyPath:#"responseError"
withMapping:errorMapping]];
[registeredServicesMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"responseRegisteredServicesCloud"
toKeyPath:#"responseRegisteredServicesCloud"
withMapping:cloudMapping]];
[[RKObjectManager sharedManager] addResponseDescriptor:[RKResponseDescriptor responseDescriptorWithMapping:registeredServicesMapping
method:RKRequestMethodGET
pathPattern:#"registeredServices"
keyPath:nil
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)]];
Can't figure out what seems to be the problem. When I add responseIsRegisteredServices into the keyPath: of the RKResponseDescriptor than the MusicServices array is null.
Thanks in advance.
So i've found the answer, in this line:
[registeredServicesMapping addAttributeMappingsFromDictionary:#{ #"registeredToServiceAntiVirus" : #"registeredToServiceAntiVirus",
#"registeredToServiceCloud" : #"registeredToServiceCloud",
#"registeredToServiceMusic" : #"registeredToServiceMusic",
#"registeredToServiceSong" : #"registeredToServiceSong",
#"registeredToServiceTv" : #"registeredToServiceTv", }];
I needed to change it from registeredToServiceAntiVirus to responseIsRegisteredServices .registeredToServiceAntiVirus and than it worked perfectly. This is how it looks:
[registeredServicesMapping addAttributeMappingsFromDictionary:#{ #"responseIsRegisteredServices.registeredToServiceAntiVirus" : #"registeredToServiceAntiVirus",
#"responseIsRegisteredServices.registeredToServiceCloud" : #"registeredToServiceCloud",
#"responseIsRegisteredServices.registeredToServiceMusic" : #"registeredToServiceMusic",
#"responseIsRegisteredServices.registeredToServiceSong" : #"registeredToServiceSong",
#"responseIsRegisteredServices.registeredToServiceTv" : #"registeredToServiceTv", }];
Enjoy.
Related
I have the following JSON:
{
"id": 1,
"editable": true,
"number": "1",
"name": "Text here",
"banner": "Text here",
"address": "Text here",
"city": "Text here",
"contact": "Text here",
"latitude": "Text here",
"longitude": "Text here",
"banner_id": 5,
"hours": [
{
"day": "monday",
"start": "8:00am",
"end": "5:00pm"
},
{
"day": "tuesday",
"start": "",
"end": ""
},
{
"day": "wednesday",
"start": "",
"end": ""
},
{
"day": "thursday",
"start": "",
"end": ""
},
{
"day": "friday",
"start": "",
"end": ""
},
{
"day": "saturday",
"start": "",
"end": ""
},
{
"day": "sunday",
"start": "",
"end": ""
}
]
}
I am trying to create a mapping of this object which contains an array of hours, my code is as follows:
RKObjectMapping* hoursMapping = [RKObjectMapping mappingForClass:[Hours class] ];
[hoursMapping addAttributeMappingsFromArray:#[ #"day", #"start", #"end"]];
RKObjectMapping* storeMapping = [RKObjectMapping mappingForClass:[Store class] ];
[storeMapping addAttributeMappingsFromArray:#[ #"id", #"editable", #"number", #"name", #"banner", #"address", #"city", #"contact", #"latitude", #"longitude", #"banner_id"]];
[storeMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"hours"
toKeyPath:#"hours"
withMapping:hoursMapping]];
RKResponseDescriptor *storeResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:storeMapping
method:RKRequestMethodAny
pathPattern:#"api/v2/stores.json"
keyPath:#""
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
The mapping fails and the only error returned says:
"The operation couldn't be completed"
What am I doing wrong here? How can I get this to map successfully?
Store.h
#interface Store : NSManagedObject
#property (nonatomic, retain) NSNumber * id;
#property (nonatomic, retain) NSNumber * editable;
#property (nonatomic, retain) NSString * number;
#property (nonatomic, retain) NSString * name;
#property (nonatomic, retain) NSString * banner;
#property (nonatomic, retain) NSNumber * address;
#property (nonatomic, retain) NSString * city;
#property (nonatomic, retain) NSString * contact;
#property (nonatomic, retain) NSString * latitude;
#property (nonatomic, retain) NSString * longitude;
#property (nonatomic, retain) NSNumber * banner_id;
#property (nonatomic, retain) NSSet *hours;
#end
#interface Store (CoreDataGeneratedAccessors)
- (void)addHoursObject:(Hours *)value;
- (void)removeHoursObject:(Hours *)value;
- (void)addHours:(NSSet *)values;
- (void)removeHours:(NSSet *)values;
#end
Hours.h
#interface Hours : NSManagedObject
#property (nonatomic, retain) NSString * day;
#property (nonatomic, retain) NSString * start;
#property (nonatomic, retain) NSString * end;
#end
For anyone trying to find a solution to this problem:
The problem was that I was using an Object Mapping with Core Data.
I changed all references to an Object Mapping into Entity Mappings instead. The relationship mapping is the same but now points to the Core Data entity instead of the class. Now everything works as expected.
RKEntityMapping *storeMapping = [RKEntityMapping mappingForEntityForName:#"Store" inManagedObjectStore:managedObjectStore];
storeMapping.identificationAttributes = #[#"id"];
[storeMapping addAttributeMappingsFromArray:#[ #"id", #"editable", #"number", #"name", #"banner", #"address", #"city", #"contact", #"latitude", #"longitude", #"banner_id"]];
RKEntityMapping *hoursMapping = [RKEntityMapping mappingForEntityForName:#"Hours" inManagedObjectStore:managedObjectStore];
[hoursMapping addAttributeMappingsFromArray:#[#"day", #"start", #"end"]];
[storeMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"hours" toKeyPath:#"hours" withMapping:hoursMapping]];
RKResponseDescriptor *storeResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:storeMapping
method:RKRequestMethodAny
pathPattern:#"/api/v2/stores.json"
keyPath:#""
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptor:storeResponseDescriptor];
For more information visit: https://medium.com/ios-os-x-development/restkit-tutorial-how-to-fetch-data-from-an-api-into-core-data-9326af750e10
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 have this json object that I'm trying to map:
{
totalresults: 1,
results: [
{
sources: [
"The Blog",
"The website",
],
description: "Some description."",
subjects: [
"Education"
],
imageurl: "image.jpg",
authorid: 44303,
istail: false,
tailcount: 0,
displayname: "Name of me"
}
]
}
I've created a SearchPerPage object:
#interface RestSearchPerPage : NSObject
#property (strong, nonatomic) NSNumber *totalResults;
#property (strong, nonatomic) NSArray *results;
#end
I've created a SearchResults object:
#interface SearchResults : NSObject
#property (strong, nonatomic) NSArray *sources;
#property (strong, nonatomic) NSArray *subjects;
#property (strong, nonatomic) NSString *content;
#property (strong, nonatomic) NSString *imageUrl;
#property (strong, nonatomic) NSString *authorId;
#property (strong, nonatomic) NSString *displayName;
#property (strong, nonatomic) NSNumber *isTail;
#property (strong, nonatomic) NSNumber *tailCount;
#end
I'm mapping the objects just fine, but when I'm trying to map the NSArray *sources and NSArray *subjects I always get NULL.
This is my last mapping attempt on sources:
RKObjectMapping *searchResultsMapping = [RKObjectMapping mappingForClass:[SearchResults class]];
[searchResultsMapping addAttributeMappingsFromDictionary:#{ #"sources" : #"sources",
#"subjects" : #"subjects",
#"description" : #"content",
#"imageurl" : #"imageUrl",
#"authorid" : #"authorId",
#"displayname" : #"displayName",
#"istail" : #"isTail",
#"tailcount" : #"tailCount" }];
RKObjectMapping *searchPerPageMapping = [RKObjectMapping mappingForClass:[SearchPerPage class]];
[searchPerPageMapping addAttributeMappingsFromDictionary:#{ #"totalresults" : #"totalResults" }];
[searchPerPageMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"results" toKeyPath:#"results" withMapping:searchResultsMapping]];
[[RKObjectManager sharedManager] addResponseDescriptor:[RKResponseDescriptor responseDescriptorWithMapping:searchPerPageMapping
method:self.method
pathPattern:kGetSearchPerPage
keyPath:nil
statusCodes:self.statusCode]];
Please help me because I'm lost, just don't know what to do next - have no answer to this problem. Thanks in advance.
So, the problem was that I didn't mapped the array of 'results' like that:
[searchPerPageMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"results" toKeyPath:#"results" withMapping:searchResultsMapping]];
I've edited my question and fixed it.
Are you making sure that you're initializing the arrays e.g.
NSArray *subjects = [NSArray array];
It's very common to forget this :)
I've got the following JSON coming from my webservice:
"GasPrices":{
"Ai92":{
"Price":30.1000,
"LastDate":"\/Date(1385337600000)\/",
"Votes":0
},
"Ai95":{
"Price":33.2000,
"LastDate":"\/Date(1385337600000)\/",
"Votes":0
}
I want to map it to NSDictionary, whose keys would be NSStrings and values would be of my custom class, say, PriceInfo.
What I got now with default setup is NSDictionary whose values are also NSDictionaries.
How can I achieve the desired mapping?
UPD. Here's my full setup for now.
#interface FillingStation : NSObject
#property (nonatomic, strong) NSNumber *uid;
#property (nonatomic, strong) NSString *title;
#property (nonatomic, strong) NSDictionary *fuelPrices;
#end
#interface PriceInfo : NSObject
#property (nonatomic, strong) NSNumber *price;
#property (nonatomic, strong) NSDate *lastDate;
#property (nonatomic, strong) NSNumber *votes;
#end
Configuring the mapping:
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[FillingStation class]];
[mapping addAttributeMappingsFromDictionary:#{
#"Id" : #"uid",
#"Title" : #"title",
#"GasPrices" : #"fuelPrices"
}];
This results in fuelPrices is NSDictionary with the structure:
NSString -> NSDictionary,
NSString -> NSDictionary,
...
And I want it to be:
NSString -> PriceInfo,
NSString -> PriceInfo,
...
And I don't want an intermediate dictionary in FillingStation which I can then manually map.
Okay, seems like I found the answer. Not exactly what I wanted, yet acceptable for me: https://github.com/RestKit/RestKit/wiki/Object-Mapping#handling-dynamic-nesting-attributes
I had to add another property to PriceInfo class and change fuelPrices from NSDictionary to NSSet (NSArray would also work, but I don't need ordering), so it became:
#interface FillingStation : NSObject
#property (nonatomic, strong) NSNumber *uid;
#property (nonatomic, strong) NSString *title;
#property (nonatomic, strong) NSSet *fuelPrices;
#end
#interface PriceInfo : NSObject
#property (nonatomic, strong) NSString *fuelType;
#property (nonatomic, strong) NSNumber *price;
#property (nonatomic, strong) NSDate *updateDate;
#property (nonatomic, assign) NSUInteger votes;
#end
and my mapping now looks like this:
RKObjectMapping *mapping = [RKObjectMapping mappingForClass:[FillingStation class]];
[mapping addAttributeMappingsFromDictionary:#{
#"Id" : #"uid",
#"Title" : #"title"
}];
RKObjectMapping *priceInfoMapping = [RKObjectMapping mappingForClass:[PriceInfo class]];
[priceInfoMapping setForceCollectionMapping:YES];
[priceInfoMapping addAttributeMappingFromKeyOfRepresentationToAttribute:#"fuelType"];
[priceInfoMapping addAttributeMappingsFromDictionary:#{
#"(fuelType).Price": #"price",
#"(fuelType).LastDate": #"updateDate",
#"(fuelType).Votes": #"votes"
}];
[mapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"GasPrices"
toKeyPath:#"fuelPrices"
withMapping:priceInfoMapping]];
Jastor May be what you're looking for. Nested objects directly mapped to known classes.
I Read From Google Places API
{
"html_attributions" : [
"Listings by \u003ca href=\"http://www.yellowpages.com.au/\"\u003eYellow Pages\u003c/a\u003e"
],
"results" : [
{
"geometry" : {
"location" : {
"lat" : -33.870540,
"lng" : 151.1988150
}
},
"icon" : "http://maps.gstatic.com/mapfiles/place_api/icons/cafe-71.png",
"id" : "c71365287e7606bd21a3311d21fda087830b7813",
"name" : "Pancakes on the Rocks",
"opening_hours" : {
"open_now" : true
},
"photos" : [
{
"height" : 1224,
"html_attributions" : [
"\u003ca href=\"https://plus.google.com/105663944571530352563\"\u003eJoshua Gilmore\u003c/a\u003e"
],
"photo_reference" : "CnRoAAAADF1JoE-joT2BSN4NEYn2luUF2kdIRjflFvETx0SbCnPyRp0TZz8_x7OlHCpAz2rrNXtQZyp5wd-JEjZh2FSpkM2bDGs_DqmktsClrnYkkirkCOHlnBHxedJf_Etv0DV8y9vnIbFnLJ9995Fk2u98SBIQxjojXwmV45p-9b4SurLQhxoUtErGJpwFe-k0hfgVGapK1FYjnWw",
"width" : 1632
}
],
"price_level" : 2,
"rating" : 3.90,
"reference" : "CoQBcgAAAFakUaktwUsNCr--KIaYu_hS9cbO8uMAwNE2W7xSMEZimIjc6EhMStq2LpVteXf6jy4UqeHGJh0QhDSpKMGK065jlnha2F6bG1zoLDRHtYTqV3PIOMMa8KsjJgmLUU-7GDojLvb6MHVctzMbMeTGtAOq_mm5lS_oymzDtJJsehSkEhCZ-KMMyl3qmYNHkCJ919FRGhSlbP1fVPQ_mLamjx9ELIBulb4ACg",
"types" : [ "cafe", "restaurant", "food", "establishment" ],
"vicinity" : "Harbourside Shopping Centre,Darling Harbour/227 & 229-230 Darling Drive, Sydney"
},
And i have Classes As Flow
Place Class:
#interface Place : NSObject
#property (nonatomic,strong) Geometry * geometry;
#property (nonatomic,strong) NSString * icon;
#property (nonatomic,strong) NSString * placeID;
#property (nonatomic,strong) NSString * name;
#property (nonatomic,strong) OpeningHours * opening_hours;
#property (nonatomic,strong) NSString * price_level;
#property (nonatomic,strong) NSString * rating;
#property (nonatomic,strong) NSString * vicinity;
#property (nonatomic,strong) NSSet *photos;
#property (nonatomic,strong) NSString *reference;
#end
And Photos Class:
#interface Photos : NSObject
#property (nonatomic,strong) NSNumber *height;
#property (nonatomic,strong) NSString *html_attributions;
#property (nonatomic,strong) NSString *photo_reference;
#property (nonatomic,strong) NSNumber *width;
#end
and i map With Follwoing:
RKObjectMapping *placeMapping = [RKObjectMapping mappingForClass:[Place class]];
[placeMapping addAttributeMappingsFromDictionary:#{
#"icon" : #"icon",
#"id" : #"placeID",
#"name" : #"name",
#"reference" : #"reference",
#"price_level" : #"price_level",
#"rating" : #"rating",
#"vicinity" : #"vicinity",
}];
// Create our new Author mapping
RKObjectMapping* geomtryMapping = [RKObjectMapping mappingForClass:[Geometry class]];
RKObjectMapping* locationMapping = [RKObjectMapping mappingForClass:[Location class]];
[locationMapping addAttributeMappingsFromArray:#[ #"lat", #"lng" ]];
[geomtryMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"location"
toKeyPath:#"location"
withMapping:locationMapping]];
[placeMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"geometry"
toKeyPath:#"geometry"
withMapping:geomtryMapping]];
RKObjectMapping* openingHoursMapping = [RKObjectMapping mappingForClass:[OpeningHours class]];
[openingHoursMapping addAttributeMappingsFromArray:#[#"open_now"]];
[placeMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"opening_hours" toKeyPath:#"opening_hours" withMapping:openingHoursMapping]];
RKObjectMapping* photosMapping = [RKObjectMapping mappingForClass:[Photos class]];
[photosMapping addAttributeMappingsFromArray:#[#"height",#"photo_reference",#"html_attributions",#"width"]];
[photosMapping setForceCollectionMapping:YES];
[placeMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"photos"
toKeyPath:#"photos"
withMapping:photosMapping]];
RKResponseDescriptor * responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:placeMapping
pathPattern:nil
keyPath:#""
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)];
[objectManager addResponseDescriptor:responseDescriptor];
first Question
I Photos Alawys have value Nil.
Second Question How I get "html_attributions" in the beginning of json.
keyPaths is the bit you're missing. When you say Photos is always nil, I guess you don't really get any meaningful data? To get the places you need to specify the keyPath of #"results" on your responseDescriptor.
In a similar way, you can get the html_attributions by using it as the keyPath on another set of mappings and response descriptor.