So, I have this result from the service:
{
"CustomerPromotions": [
{
"BottomTitle": "Thank you",
"IconURL": "",
"MiddleText": "399$",
"PromotionID": "123B456",
"SortOrder": 0,
"TopTitle": "Welcome to"
}
],
"CustomerStatus": 1,
"CustomerVoucherIcon": "",
"CustomerVoucherText": "",
"CustomerVoucherTitle": "",
"ErrorID": 0,
"ErrorMessage": "",
"FeedbackIndicator": false,
"FeedbackLowerText": "",
"FeedbackTitle": "",
"HPTopTitle": "Hello world",
"LocalCurrencySign": "$",
"LocalCurrencyValue": "3.30",
"LocalTime": "20:30",
"LocalWeather": "-5",
"PopUpTopTitle": ""
}
But for some reason I can't map CustomerPromotions it into an array, this is how my 2 objects looks like:
This is CustomerLogin.h:
#interface CustomerLogin : NSObject
#property (nonatomic) NSArray *customerPromotions;
#property (strong, nonatomic) NSNumber *customerStatus;
#property (strong, nonatomic) NSString *customerVoucherIcon;
#property (strong, nonatomic) NSString *customerVoucherText;
#property (strong, nonatomic) NSString *customerVoucherTitle;
#property (strong, nonatomic) NSNumber *errorID;
#property (strong, nonatomic) NSString *errorMessage;
#property (strong, nonatomic) NSNumber *feedbackIndicator;
#property (strong, nonatomic) NSString *feedbackLowerText;
#property (strong, nonatomic) NSString *feedbackTitle;
#property (strong, nonatomic) NSString *hpTopTitle;
#property (strong, nonatomic) NSString *localCurrencySign;
#property (strong, nonatomic) NSString *localCurrencyValue;
#property (strong, nonatomic) NSString *localTime;
#property (strong, nonatomic) NSString *localWeather;
#property (strong, nonatomic) NSString *popUpTopTitle;
#end
This is 'CustomerPromotions`:
#interface CustomerPromotions : NSObject
#property (strong, nonatomic) NSString *bottomTitle;
#property (strong, nonatomic) NSString *iconURL;
#property (strong, nonatomic) NSString *middleText;
#property (strong, nonatomic) NSString *promotionID;
#property (strong, nonatomic) NSNumber *sortOrder;
#property (strong, nonatomic) NSString *topTitle;
#end
This is the mapping:
RKObjectMapping *customerLoginMapping = [RKObjectMapping mappingForClass:[CustomerLogin class]];
[customerLoginMapping addAttributeMappingsFromDictionary:#{ #"CustomerStatus" : #"customerStatus",
#"CustomerVoucherIcon" : #"customerVoucherIcon",
#"CustomerVoucherText" : #"customerVoucherText",
#"CustomerVoucherTitle" : #"customerVoucherTitle",
#"ErrorID" : #"errorID",
#"ErrorMessage" : #"errorMessage",
#"FeedbackIndicator" : #"feedbackIndicator",
#"FeedbackLowerText" : #"feedbackLowerText",
#"FeedbackTitle" : #"feedbackTitle",
#"HPTopTitle" : #"hpTopTitle",
#"LocalCurrencySign" : #"localCurrencySign",
#"LocalCurrencyValue" : #"localCurrencyValue",
#"LocalTime" : #"localTime",
#"LocalWeather" : #"localWeather",
#"PopUpTopTitle" : #"popUpTopTitle" }];
RKObjectMapping *customerPromotionsMapping = [RKObjectMapping mappingForClass:[CustomerPromotions class]];
[customerPromotionsMapping addAttributeMappingsFromDictionary:#{ #"BottomTitle" : #"bottomTitle",
#"IconURL" : #"iconURL",
#"MiddleText" : #"middleText",
#"PromotionID" : #"promotionID",
#"SortOrder" : #"sortOrder",
#"TopTitle" : #"topTitle" }];
[customerLoginMapping addRelationshipMappingWithSourceKeyPath:#"customerPromotions" mapping:customerPromotionsMapping];
[[RKObjectManager sharedManager] addResponseDescriptor:[RKResponseDescriptor responseDescriptorWithMapping:customerLoginMapping
method:RKRequestMethodPOST
pathPattern:#"CustomerLogin"
keyPath:nil
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)]];
This is the POST request:
NSDictionary *params = #{ #"AppID" : #"1",
#"AppPassword" : #"String content",
#"Password" : #"password",
#"UserName" : #"username" };
[[RKObjectManager sharedManager] postObject:[[CustomerLogin alloc] init]
path:#"CustomerLogin"
parameters:params
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSLog(#"%#", operation.HTTPRequestOperation.responseString);
NSLog(#"%#", mappingResult.array);
CustomerLogin *customer = [mappingResult.array lastObject];
NSLog(#"%#", customer.customerPromotions);
NSLog(#"%#", customer.hpTopTitle);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
NSLog(#"%#", error.localizedDescription);
}];
It just looks like your key name is wrong. You use a source key only, which means the source and destination should match but they don't actually match. Try:
RKRelationshipMapping *relationMapping = [RKRelationshipMapping relationshipMappingFromKeyPath:#"CustomerPromotions" toKeyPath:#"customerPromotions" withMapping:customerPromotionsMapping];
[customerLoginMapping addPropertyMapping:relationMapping];
Related
I have a JSON that looks like this :
{
"club": [
{
"titles": "1",
"league": "epl",
"country": "england",
}
}
And I have created a property like this :
#property (strong, nonatomic) NSMutableArray <Clubs> *club;
The club property inherits from the Clubs class which has the titles, leagues and country properties.
When I try to create a dictionary with that data model, I am unable to access the properties inside the club array.
Am I creating the data model incorrectly ?
Creating the dictionary:
for (NSDictionary *dictionary in responseObject) {
if (![self.searchText isEqualToString:#""]) {
self.predictiveProductsSearch = [[PerdictiveSearch alloc]initWithDictionary:dictionary error:nil];
self.predictiveTableView.dataSource = self;
[self.predictiveTableView reloadData];
self.predictiveTableView.hidden = NO;
}
}
Clubs class
#import <JSONModel/JSONModel.h>
#protocol Clubs #end
#interface Clubs : JSONModel
#property (strong, nonatomic) NSString <Optional> * titles;
#property (strong, nonatomic) NSString <Optional> * league;
#property (strong, nonatomic) NSString <Optional> * country;
#property (strong, nonatomic) NSString <Optional> * topGS;
#property (strong, nonatomic) NSString <Optional> * GoalSc;
#property (strong, nonatomic) NSString <Optional> * TransferBudget;
#end
Please use below code to achieve JSON Model saving:
_club = [[NSMutableArray alloc]init];
NSDictionary *responseObject = #{
#"club": #[
#{
#"titles": #"1",
#"league": #"epl",
#"country": #"england"
}]
};
NSArray *newResponseObject = [responseObject objectForKey:#"club"];
for (NSDictionary *dictionary in newResponseObject) {
Clubs *objClubs = [[Clubs alloc]initWithDictionary:dictionary error:nil];
[_club addObject:objClubs];
}
NSLog(#"%#",[_club objectAtIndex:0]);
which print like below :
<Clubs>
[titles]: 1
[country]: england
[GoalSc]: <nil>
[league]: epl
[topGS]: <nil>
[TransferBudget]: <nil>
</Clubs>
I have modeled my api result as following:
#import "PTPDestination.h"
#interface PTPIndex : PTPBaseEntity
#property (strong, nonatomic) NSNumber * citiesCount;
#property (strong, nonatomic) NSNumber * hotelsCount;
#property (strong, nonatomic) NSArray<PTPDestination *> * top_destinations;
#end
I also modeled PTPDestination like this:
#interface PTPDestination : PTPBaseEntity
#property (assign, nonatomic) NSNumber * id;
#property (assign, nonatomic) NSNumber * min_price;
#property (assign, nonatomic) NSNumber * max_discount;
#property (assign, nonatomic) NSString * title;
#end
And I call my api with AFNetworking like this:
AFHTTPSessionManager * manager = [self createAPISessionManager];
[manager GET:[self createServiceUrlWithMethod:#"someURL"] parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSError * error = nil;
PTPIndex * index = [[PTPIndex alloc] initWithDictionary:responseObject error:&error];
if (error) {
callback (nil, [PTPApiCenteralizedErrorHandler getErrorFromApiError:error task:task responseObject:responseObject]);
return;
}
callback (index, nil);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
callback (nil, [PTPApiCenteralizedErrorHandler getErrorFromApiError:error task:task]);
}];
The problem is with array of destinations. I don't know why the array is not converted to PTPDestination object and it remains as an array of NSDictionaries.
Why this happens and how can I have an array of my custom class?
No, JSON Model Also Converted the Array to JSONObject, if you want to access the PTPDestination class properties.
PTPIndex class
#import "JSONModel.h"
#interface PTPIndex : JSONModel
#property (strong, nonatomic) NSNumber * citiesCount;
#property (strong, nonatomic) NSNumber * hotelsCount;
#property (strong, nonatomic) NSArray<PTPDestination *> * top_destinations;
#end
PPTPDestination class
#import "JSONModel.h"
#interface PTPDestination : JSONModel
#property (assign, nonatomic) NSNumber * id;
#property (assign, nonatomic) NSNumber * min_price;
#property (assign, nonatomic) NSNumber * max_discount;
#property (assign, nonatomic) NSString * title;
#end
NSDictionary "data" from the network Response
PTPIndex *ptpInd = [[PTPIndex alloc] initWithDictionary:data error:&error];
find the total number of PTPDestination and run in the loop.
You can access the object like this.
PTPDestination *ptpdest = [ptpInd PTPDestination[0]];
I have a problem, can't map a nested object of json. The problem is with the 'capacities' key.
This is the error:
restkit.object_mapping:RKMappingOperation.m:830 Did not find mappable relationship value keyPath 'capacities'
I know that the problem is with the mapping itself, but just can't figure what:
RKObjectMapping *capacityMapping = [RKObjectMapping mappingForClass:[Capacity class]];
[capacityMapping addAttributeMappingsFromDictionary:#{ #"capacityText" : #"capacityText",
#"priceDescriptionText" : #"priceDescriptionText",
#"priceText" : #"priceText" }];
RKObjectMapping *colorsMapping = [RKObjectMapping mappingForClass:[Colors class]];
[colorsMapping addAttributeMappingsFromDictionary:#{ #"ID" : #"idNum",
#"Name" : #"name",
#"colorHex" : #"colorHex",
#"imageUrl" : #"imageURL" }];
RKObjectMapping *deviceDataMapping = [RKObjectMapping mappingForClass:[DeviceData class]];
[deviceDataMapping addAttributeMappingsFromDictionary:#{ #"device.ID" : #"idNum",
#"device.Name" : #"name",
#"device.additionalFeatures" : #"additionalFeatures",
#"device.deviceName" : #"deviceName",
#"device.mainFeatures" : #"mainFeatures",
#"device.supportPagesLinks" : #"supportPagesLinks",
#"device.whatsInTheKit" : #"whatsInTheKit" }];
[deviceDataMapping addRelationshipMappingWithSourceKeyPath:#"capacities" mapping:capacityMapping];
[capacityMapping addRelationshipMappingWithSourceKeyPath:#"colors" mapping:colorsMapping];
[deviceDataMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"responseError"
toKeyPath:#"responseError"
withMapping:errorMapping]];
[[RKObjectManager sharedManager] addResponseDescriptor:[RKResponseDescriptor responseDescriptorWithMapping:deviceDataMapping
method:RKRequestMethodGET
pathPattern:#"devices/:boneID"
keyPath:nil
statusCodes:RKStatusCodeIndexSetForClass(RKStatusCodeClassSuccessful)]];
This is the DeviceData class:
#interface DeviceData : NSObject
#property (nonatomic) ResponseError *responseError;
#property (copy, nonatomic) NSString *idNum;
#property (copy, nonatomic) NSString *name;
#property (copy, nonatomic) NSString *additionalFeatures;
#property (copy, nonatomic) NSString *deviceName;
#property (copy, nonatomic) NSString *mainFeatures;
#property (copy, nonatomic) NSString *supportPagesLinks;
#property (copy, nonatomic) NSString *whatsInTheKit;
#property (nonatomic) NSArray *capacities;
#property (assign, nonatomic) NSInteger boneID;
#end
This is the Capacity class:
#interface Capacity : NSObject
#property (copy, nonatomic) NSString *capacityText;
#property (nonatomic) NSArray *colors;
#property (copy, nonatomic) NSString *priceDescriptionText;
#property (copy, nonatomic) NSString *priceText;
#end
This is the Colors class:
#interface Colors : NSObject
#property (copy, nonatomic) NSString *idNum;
#property (copy, nonatomic) NSString *name;
#property (copy, nonatomic) NSString *colorHex;
#property (copy, nonatomic) NSString *imageURL;
#end
This is the json:
{
"responseError": null,
"device": {
"ID": null,
"Name": null,
"additionalFeatures": "additional features text",
"capacities": [
{
"capacityText": "16GB",
"colors": [
{
"ID": null,
"Name": null,
"colorHex": "#a68f76",
"imageUrl": "iphone_5s_black.png"
},
{
"ID": null,
"Name": null,
"colorHex": "#a9a9a9",
"imageUrl": "iphone_5s_black.png"
},
{
"ID": null,
"Name": null,
"colorHex": "#616065",
"imageUrl": "iphone_5s_black.png"
}
],
"priceDescriptionText": “iPhone 5S",
"priceText": "750$"
},{
"capacityText": “32GB",
"colors": [
{
"ID": null,
"Name": null,
"colorHex": "#a68f76",
"imageUrl": "iphone_5s_black.png"
},
{
"ID": null,
"Name": null,
"colorHex": "#a9a9a9",
"imageUrl": “iphone_5s_black.png"
},
{
"ID": null,
"Name": null,
"colorHex": "#616065",
"imageUrl": “iphone_5s_black.png"
}
],
"priceDescriptionText": “iPhone 5S",
"priceText": "750$"
}
],
"deviceName": "iPhone 5s",
"mainFeatures": “some main features text",
"supportPagesLinks": [
{
"linkText": “restore",
"linkUrl": “restore.pdf"
}],
"whatsInTheKit": "what inside the kit text"
}
}
Because your response descriptor has a nil key path and you use device.xxx in all source key paths of the deviceMapping you need to have an explicit relationship mapping so you can specify the source and destination key paths:
RKRelationshipMapping *capacitiesMapping = [RKRelationshipMapping relationshipMappingFromKeyPath:#"device.capacities" toKeyPath:#"capacities" withMapping:capacityMapping];
[deviceDataMapping addPropertyMapping:capacitiesMapping];
i wanna to map object in Google Places Api Photos
"photos" : [
{
"height" : 1224,
"html_attributions" : [
"\u003ca href=\"https://plus.google.com/105663944571530352563\"\u003eJoshua Gilmore\u003c/a\u003e"
],
"photo_reference" : "CnRoAAAAzuH4E1LVJHMdXNYbewoxcPE-qHizCE6pmOGjckeaCTKSL7xGVzLuwGxu7kx44bCWIZinMx4jkd8eenALB7w7jNRFrzE3hip2ld7096SI9D4sE2WpXQ1QH-iTQm7qhx4i6QSGGeXKjA9SfT4N6krwzRIQr1mulgyuKHP-2s_TJWIahhoUgxfccds3VAH2bj_CIQYzbAQZRhc",
"width" : 1632
}
],
i try with this code but photos is still nil
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) NSArray *photos;
#property (nonatomic,strong) NSString *reference;
#end
Photos Class
#import <Foundation/Foundation.h>
#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:
RKObjectMapping *placeMapping = [RKObjectMapping mappingForClass:[Place class]];
[placeMapping addAttributeMappingsFromDictionary:#{
#"icon" : #"icon",
#"id" : #"placeID",
#"name" : #"name",
#"reference" : #"reference",
#"price_level" : #"price_level",
#"rating" : #"rating",
#"vicinity" : #"vicinity",
}];
RKObjectMapping* photosMapping = [RKObjectMapping mappingForClass:[Photos class]];
[photosMapping addAttributeMappingsFromArray:#[#"height",#"photo_reference",#"html_attributions",#"width"]];
[placeMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"photos"
toKeyPath:#"photos"
withMapping:photosMapping]];
I don't know how to map photos as array in Place Class .
Any one can help me ?
i have a problem in reading JSON by JSONModel library https://github.com/icanzilb/JSONModel
and use the KivaDemo at the JSonModel app,the json :
"loans": [
{
"id": 547665,
"name": "Veronica",
"description": {
"languages": [
"en"
]
},
"status": "fundraising",
"funded_amount": 0,
i want to get the "en" ,
#interface KivaFeed : JSONModel
#property (strong, nonatomic) NSArray<LoanModel, ConvertOnDemand>* loans;
#property (strong, nonatomic) Paging *paging;
#end
#protocol LoanModel #end
#interface LoanModel : JSONModel
#property (strong, nonatomic) NSString* name;
#property (strong, nonatomic) NSString* status;
#property (strong, nonatomic) NSString* use;
#property (strong, nonatomic) NSString* id;
#property (strong, nonatomic) NSString* funded_amount;
#property (strong, nonatomic) LocationModel* location;
#property (strong, nonatomic) Image* image;
#property (strong, nonatomic) Description* description;
#end
#interface Description : JSONModel
#property (strong, nonatomic) NSArray<Languages, ConvertOnDemand>* languages;
#end
#protocol Languages #end
#interface Languages : JSONModel
#end
kiva = [[KivaFeed alloc] initFromURLWithString:#"http://api.kivaws.org/v1/loans/search.json?status=fundraising"
completion:^(JSONModel *model, JSONModelError *e) {
[table reloadData];
NSLog(#"kiva.paging.page:%#",kiva.paging.page);
if (e) {
[[NSAlert alertWithError:e] beginSheetModalForWindow:self.view.window modalDelegate:nil didEndSelector:nil contextInfo:nil];
}
[self setLoaderVisible:NO];
}];
LoanModel* loan = kiva.loans[row];
NSString* message = [NSString stringWithFormat:#"%# from %#(%#) needs a loan %#",
loan.name, loan.location.country, loan.location.countryCode, loan.use
];
NSLog(#"loan:%#",loan.id);
NSLog(#"loan:%#",loan.funded_amount);
NSLog(#"loan.image.id:%#",loan.image.id);
NSLog(#"loan.description.languages:%#",loan.description.languages[0]);
last it give me 2013-04-15 13:16:09.163 JSONModelDemo_OSX[2308:303] loan.description.languages:(null). how to get the en,what mistake at my code?
modify as :
#interface Description : JSONModel
#property (strong, nonatomic) NSArray* languages;
#end
all is ok