Well, I should remember you I am still a beginner in iOS development with objective c. And maybe because of this, the solution is simple but I canĀ“t see it. I have a json who is armed in the following way :
{
"origin_addresses": [
"Test"
],
"rows": [
{
"elements": [
{
"distance": {
"text": "0.3 km",
"value": 339
},
"duration": {
"text": "1 min",
"value": 82
},
"status": "OK"
}
]
}
],
"status": "OK"
}
The app can consume the service without problems. My goal is to reach the distance attribute. Which I do as follows. I use a foreach to get through the array rows and then another foreach to get through the array elements.
for (BPCGARows *item in googleAddress.rows) {
NSLog(#"rows : %#", item);
for (BPCGAElements *element in item.elements) {
}
}
When I'm debugging the app, my first for each works without problems, but when I access the second foreach the (BPCGAElements * element in item.elements) the app crashes. Finally I can't print the item.elements in a log either. The error message is as follows:
'NSInvalidArgumentException', reason: '-[__NSSingleEntryDictionaryI
elements]: unrecognized selector sent to instance 0x281c75da0'
header BPCGADistance :
#interface BPCGADistance : MBOInspectableModel
#property (nonatomic, strong, readonly) NSString *text;
#property (nonatomic, strong, readonly) NSNumber *value;
#end
main BPCGADistance:
#interface BPCGADistance()
#property (nonatomic, strong, setter=text:) NSString *text;
#property (nonatomic, strong, setter=value:) NSNumber *value;
#end
header BPCGAElements :
#interface BPCGADistance : MBOInspectableModel
#property (nonatomic, strong, readonly) NSString *text;
#property (nonatomic, strong, readonly) NSNumber *value;
#end
main BPCGAElements:
#interface BPCGADistance()
#property (nonatomic, strong, setter=text:) NSString *text;
#property (nonatomic, strong, setter=value:) NSNumber *value;
#end
This is my NSLog(#"rows : %#", item),
I emphasize that by using the item.elements to print the crashea app on the console. ;
Related
I'm using KeyValueObjectMapping to convert JSON string to Model class.
Here is JSON string:
{
"id_str": "123456",
"name": "Some Name",
"protected": false,
"created_at": "Tue Mar 31 18:01:12 +0000 2009",
"tweets" : [
{
"created_at" : "Sat Apr 14 00:20:07 +0000 2012",
"id_str" : 190957570511478784,
"text" : "Tweet text",
"comments": {
"id_str":"2343",
"text":"This is comment1"
}
},
{
"created_at" : "Sat Apr 14 00:20:07 +0000 2012",
"id_str" : 190957570511478784,
"text" : "Tweet text",
"comments": {
"id_str":"2343",
"text":"This is comment2"
}
}
]
}
For which I have created model classes, like this:
For User,
#interface User : SRKObject
#property(nonatomic, strong) NSString *idStr;
#property(nonatomic, strong) NSString *name;
#property(nonatomic, strong) BOOL protected;
#property(nonatomic, strong) NSDate *createdAt;
#property(nonatomic, strong) NSArray *tweets;
#end
For tweets,
#interface Tweet : SRKObject
#property(nonatomic, strong) NSString *idStr;
#property(nonatomic, strong) NSString *text;
#property(nonatomic, strong) NSDate *createdAt;
#property(nonatomic, strong) Comments *comments;
#end
For Comments,
#interface Comments : SRKObject
#property(nonatomic, strong) NSString *idStr;
#property(nonatomic, strong) NSString *text;
#end
It is working absolutely fine and I'm getting tweets in array. And I get tweets as user.tweets.
To save this in database, I'm using SharkORM for ORM. But while saving either it crash or don't save tweets at all.
Here is the issue open in repo (but using different example) - https://github.com/sharksync/sharkorm/issues/78
The reason for the crash was the persistence of an array of Tweets stored in a User object as opposed to storing them as a separate class. See: This
Ultimately what you want to end up with is ....
#interface Tweet : NSObject
#property(nonatomic, strong) User* user;
#property(nonatomic, strong) NSString *idStr;
#property(nonatomic, strong) NSString *text;
#property(nonatomic, strong) NSDate *createdAt;
#end
As storing all tweets in an array object will just tie you in knots quickly (no searching, ever increasing save times).
So, when you get the JSON down, you can map the first class no problem, then iterate the tweets creating objects which are related to the User class.
Relating objects is just a case of setting the .user property with the relevant User entity which you have either created or queried for.
Thanks to #Adrian_H for the efforts. I figured out the solution and posting here.
I have added below code in Tweet & Comments model to save tweets as NSArray and comments as model object and it worked.
- (void)encodeWithCoder:(NSCoder *)aCoder;
-(id)initWithCoder:(NSCoder *)aDecoder;
I have these properties in the header file.
#property (copy, nonatomic) NSString<Optional>* guidId;
#property (copy, nonatomic) NSDate* created_at;
#property (copy, nonatomic) NSNumber<Ignore>* longitude;
#property (copy, nonatomic) NSNumber<Ignore>* latitude;
#property (copy, nonatomic) NSNumber* altitude;
#property (copy, nonatomic) NSNumber* relative_altitude;
#property (copy, nonatomic) NSNumber* value;
#property (copy, nonatomic) NSString<Optional>* scale;
#property (copy, readonly, nonatomic, getter=getReadingTypeDescription) NSString* name;
#property (assign, nonatomic) WEEReadingType readingType;
#property (copy, nonatomic) NSString* name;
#property (strong, nonatomic) NSMutableArray* location;
Though it is strange Optional and Ignore are not respected.
In the implementation file I override these two methods.
// This one because when converting to JSON from Model I need specific properties only and Ignore is not for this purpose
- (NSString *)toJSONString
{
return [super toJSONStringWithKeys:
#[
#"guidId",
#"location",
#"altitude",
#"relative_altitude",
#"scale",
#"name",
#"value",
#"created_at"
]];
}
// And this one for the enum property that I want to ignore, but I found out I get an error when using [JSONModel arrayOfModelsFromDictionaries:json error:&error] that Optional or Ignore is not respected.
+ (BOOL)propertyIsIgnored:(NSString *)propertyName
{
if ([propertyName isEqualToString:#"readingType"] ||
[propertyName isEqualToString:#"guidId"] ||
[propertyName isEqualToString:#"longitude"] ||
[propertyName isEqualToString:#"latitude"])
{
return YES;
}
return NO;
}
Example of JSON I need to convert to my model.
[
{
"created_at": "2015-03-20T19:26:28.000Z",
"location": [
40.70739851802653,
-74.005788154969
],
"altitude": 4.063048774263429,
"relative_altitude": 0.0,
"name": "pressure",
"value": 1014.718704223633,
"scale": "mb"
},
{
"created_at": "2015-03-20T19:26:28.000Z",
"location": [
40.70739851802653,
-74.005788154969
],
"altitude": 4.063048774263429,
"relative_altitude": 0.0,
"name": "pressure",
"value": 1014.718704223633,
"scale": null
}
]
The above with [JSONModel arrayOfModelsFromDictionaries:json error:&error] will throw the following error.
Error Domain=JSONModelErrorDomain Code=1 "Invalid JSON data: Value of required model key scale is null" UserInfo=0x170265cc0 {NSLocalizedDescription=Invalid JSON data: Value of required model key scale is null, kJSONModelKeyPath=[46].scale}
Any ideas what is wrong?
Just try using +(BOOL)propertyIsOptional:(NSString*)propertyName
Using this on .m file
+(BOOL)propertyIsOptional:(NSString*)propertyName
{
if([propertyName isEqualToString:#"somePropertyNameWhichShouldbeIgnored"])
return YES;
return NO;
}
I need some help configuring RestKit 0.2x... I am returning JSON with a Schedule object and ScheduleEntries as a nested array.
Sample JSON:
[{
"id": 3,
"name": "Schedule 9",
"sWeek": 9,
"sYear": 2014,
"companyId": 1,
"createdOn": "2014-02-11T22:01:33.547",
"modifiedOn": null,
"companyCode": "0001",
"isActive": true,
"notes": "This is a test note",
"scheduleEntries": [{
"id": 15,
"companyId": 1,
"userId": "a7e46520-8db7-4452-821d-7938b23fcd07",
"scheduleId": 3,
"jobId": 5,
"isActive": true,
"createdOn": "2014-02-11T22:01:33.993",
"modifiedOn": null,
"sWeek": 11,
"sYear": 2014,
"startTime": "2014-03-10T08:48:00",
"endTime": "2014-03-10T08:48:00"
}, {
"id": 16,
"companyId": 1,
"userId": "a7e46520-8db7-4452-821d-7938b23fcd07",
"scheduleId": 3,
"jobId": 3,
"isActive": true,
"createdOn": "2014-02-11T22:01:34.003",
"modifiedOn": null,
"sWeek": 11,
"sYear": 2014,
"startTime": "2014-03-11T00:57:00",
"endTime": "2014-03-11T00:57:00"
}, {....
NSManagedObjects
#interface Schedule : NSManagedObject
#property (nonatomic, retain) NSNumber * scheduleId;
#property (nonatomic, retain) NSString * name;
#property (nonatomic, retain) NSNumber * sWeek;
#property (nonatomic, retain) NSNumber * sYear;
#property (nonatomic, retain) NSNumber * companyId;
#property (nonatomic, retain) NSString * companyCode;
#property (nonatomic, retain) NSString * notes;
#property (nonatomic, retain) NSNumber * isActive;
#property (nonatomic, retain) NSDate * createdOn;
#property (nonatomic, retain) NSDate * modifiedOn;
#property (nonatomic, retain) NSSet * scheduleEntries;
#end
#implementation Schedule
#dynamic scheduleId;
#dynamic name;
#dynamic sWeek;
#dynamic sYear;
#dynamic companyId;
#dynamic companyCode;
#dynamic notes;
#dynamic isActive;
#dynamic createdOn;
#dynamic modifiedOn;
#dynamic scheduleEntries;
#end
#interface ScheduleEntry : NSManagedObject
#property (nonatomic, retain) NSNumber * scheduleEntryId;
#property (nonatomic, retain) NSNumber * companyId;
#property (nonatomic, retain) NSNumber * usrId;
#property (nonatomic, retain) NSNumber * scheduleId;
#property (nonatomic, retain) NSNumber * jobId;
#property (nonatomic, retain) NSNumber * sWeek;
#property (nonatomic, retain) NSNumber * sYear;
#property (nonatomic, retain) NSDate * startTime;
#property (nonatomic, retain) NSDate * endTime;
#property (nonatomic, retain) NSNumber * isActive;
#property (nonatomic, retain) NSDate * createdOn;
#property (nonatomic, retain) NSDate * modifiedOn;
#end
#implementation ScheduleEntry
#dynamic scheduleEntryId;
#dynamic companyId;
#dynamic usrId;
#dynamic scheduleId;
#dynamic jobId;
#dynamic sWeek;
#dynamic sYear;
#dynamic startTime;
#dynamic endTime;
#dynamic isActive;
#dynamic createdOn;
#dynamic modifiedOn;
#end
Code:
RKManagedObjectStore *managedObjectStore = [RKManagedObjectStore defaultStore];
// Create mapping for entity
RKEntityMapping *scheduleEntryMapping = [RKEntityMapping mappingForEntityForName:#"ScheduleEntry" inManagedObjectStore:managedObjectStore];
scheduleEntryMapping.identificationAttributes = #[#"scheduleEntryId"];
[scheduleEntryMapping addAttributeMappingsFromDictionary:#{
#"id" : #"scheduleEntryId",
#"companyId": #"companyId",
#"usrId" : #"usrId",
#"scheduleId" : #"scheduleId",
#"jobId" : #"jobId",
#"isActive": #"isActive",
#"sWeek": #"sWeek",
#"sYear": #"sYear",
#"startTime": #"startTime",
#"endTime": #"endTime",
#"createdOn": #"createdOn",
#"modifiedOn": #"modifiedOn"
}];
RKEntityMapping *scheduleMapping = [RKEntityMapping mappingForEntityForName:#"Schedule" inManagedObjectStore:managedObjectStore];
scheduleMapping.identificationAttributes = #[#"scheduleId"];
[scheduleMapping addAttributeMappingsFromDictionary:#{
#"id" : #"scheduleId",
#"name": #"name",
#"sWeek": #"sWeek",
#"sYear": #"sYear",
#"companyId": #"companyId",
#"companyCode": #"companyCode",
#"notes": #"notes",
#"isActive": #"isActive",
#"createdOn": #"createdOn",
#"modifiedOn": #"modifiedOn",
#"scheduleEntries": #"scheduleEntries"
}];
[scheduleMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"scheduleEntries"
toKeyPath:#"scheduleEntries"
withMapping:scheduleEntryMapping]];
This code is very close to the RestKit 0.2x example but I can't seem to get it to work. I can get a single object just fine, but when it comes to objects that have nested data I'm stuck. It has been a few days working on this with no results. The error says I'm setting the keyPath more than once but I don't see it. Any help would be appreciated.
You just need to remove #"scheduleEntries": #"scheduleEntries" from the mapping dictionary on scheduleMapping because that is added (and therefore duplicated) by the relationship mapping.
Other than that things look correct.
Facing problem while getting a array of json.
I am using JsonModel library for json handelling.
My json data is:
[
{
"TSCard_id": 100,
"TSCardBackend_id": "TSu1t1",
"TSCard_date": "10/11/2013",
"TSCard_resource_id": "",
"TSCard_resource_name": "",
"TSCard_job_id": "JOB_M2156 ",
"TSCard_job_desc": "BAGARIA MILLIPORE - BOM ",
"TSCard_activity_id": "B03",
"TSCard_activity_desc": "Closing",
"TSCard_hours": "4.0",
"TSCard_chargeableflag": "0",
"TSCard_desc": "Description:",
"TSCard_syncflag": "0",
"TSCard_flag": "",
"user_id": "1"
},
{
"TSCard_id": 101,
"TSCardBackend_id": "TSu1t2",
"TSCard_date": "12/11/2013",
"TSCard_resource_id": "",
"TSCard_resource_name": "",
"TSCard_job_id": "JOB_B0002",
"TSCard_job_desc": "ABB LIMITED - BLR ",
"TSCard_activity_id": "NB01",
"TSCard_activity_desc": "Admin ",
"TSCard_hours": "5.0",
"TSCard_chargeableflag": "1",
"TSCard_desc": "Description:",
"TSCard_syncflag": "0",
"TSCard_flag": "",
"user_id": "1"
}
]
Above json has 2 objects of type TSCard class
//TSCard.h
#import <Foundation/Foundation.h>
#import <JSONModel.h>
#protocol TSCard #end
#interface TSCard : JSONModel
#property (nonatomic, retain) NSString *TSCard_id;
#property (nonatomic, retain) NSString *TSCardBackend_id;
#property (nonatomic, retain) NSString *TSCard_date;
#property (nonatomic, retain) NSString *TSCard_resource_id;
#property (nonatomic, retain) NSString *TSCard_resource_name;
#property (nonatomic, retain) NSString *TSCard_job_id;
#property (nonatomic, retain) NSString *TSCard_job_desc;
#property (nonatomic, retain) NSString *TSCard_activity_id;
#property (nonatomic, retain) NSString *TSCard_activity_desc;
#property (nonatomic, retain) NSString *TSCard_hours;
#property (nonatomic, retain) NSString *TSCard_chargeableflag;
#property (nonatomic, retain) NSString *TSCard_desc;
#property (nonatomic, retain) NSString *TSCard_syncflag;
#property (nonatomic, retain) NSString *TSCard_flag;
#property (nonatomic, retain) NSString *user_id;
#end
And I am making a class for array of type TSCard
//GetCardData.h
#import <JSONModel.h>
#import "TSCard.h"
#interface GetCardData : JSONModel
#property(strong,nonatomic)NSArray<TSCard>* myDataArray;
#end
then I parsing json as below:
NSError* err = nil;
GetCardData *c = [[GetCardData alloc] initWithString:jsonString error:&err];
NSLog(#"%d",c.myDataArray.count);
NSLog Error:
Error Domain=JSONModelErrorDomain Code=1 "Invalid JSON data: Attempt to initialize JSONModel object using initWithDictionary:error: but the dictionary parameter was not an 'NSDictionary'." UserInfo=0x8265490 {NSLocalizedDescription=Invalid JSON data: Attempt to initialize JSONModel object using initWithDictionary:error: but the dictionary parameter was not an 'NSDictionary'.}
I can't find where I am wrong...can anybody suggest the right way of using JsonModel and parsing a jsonString to array of TSCard objects correctly.
Try using following code for parsing your json and getting array
NSMutableArray *yourArray = [TSCard arrayOfModelsFromDictionaries:jsonString];
Than create and assign
GetCardData *objCardData = [[GetCardData alloc] init];
objCardData.myDataArray = yourArray;
or you need to change your JSONString as follow
{
"myDataArray": [
{
"TSCard_id": 100,
"TSCardBackend_id": "TSu1t1",
"TSCard_date": "10/11/2013",
"TSCard_resource_id": "",
"TSCard_resource_name": "",
"TSCard_job_id": "JOB_M2156 ",
"TSCard_job_desc": "BAGARIA MILLIPORE - BOM ",
"TSCard_activity_id": "B03",
"TSCard_activity_desc": "Closing",
"TSCard_hours": "4.0",
"TSCard_chargeableflag": "0",
"TSCard_desc": "Description:",
"TSCard_syncflag": "0",
"TSCard_flag": "",
"user_id": "1"
},
{
"TSCard_id": 101,
"TSCardBackend_id": "TSu1t2",
"TSCard_date": "12/11/2013",
"TSCard_resource_id": "",
"TSCard_resource_name": "",
"TSCard_job_id": "JOB_B0002",
"TSCard_job_desc": "ABB LIMITED - BLR ",
"TSCard_activity_id": "NB01",
"TSCard_activity_desc": "Admin ",
"TSCard_hours": "5.0",
"TSCard_chargeableflag": "1",
"TSCard_desc": "Description:",
"TSCard_syncflag": "0",
"TSCard_flag": "",
"user_id": "1"
}
]
}
Than your code will definitely work. Tell me if need more help.
For your problem, I personally recommend BWJSONMatcher. You don't have to do anything else or declare any protocol apart from your data model:
#interface TSCard : NSObject
#property (nonatomic, strong) NSString *TSCard_id;
#property (nonatomic, strong) NSString *TSCardBackend_id;
#property (nonatomic, strong) NSString *TSCard_date;
#property (nonatomic, strong) NSString *TSCard_resource_id;
#property (nonatomic, strong) NSString *TSCard_resource_name;
#property (nonatomic, strong) NSString *TSCard_job_id;
#property (nonatomic, strong) NSString *TSCard_job_desc;
#property (nonatomic, strong) NSString *TSCard_activity_id;
#property (nonatomic, strong) NSString *TSCard_activity_desc;
#property (nonatomic, strong) NSString *TSCard_hours;
#property (nonatomic, strong) NSString *TSCard_chargeableflag;
#property (nonatomic, strong) NSString *TSCard_desc;
#property (nonatomic, strong) NSString *TSCard_syncflag;
#property (nonatomic, strong) NSString *TSCard_flag;
#property (nonatomic, strong) NSString *user_id;
#end
You can then get your array with one neatly short line:
NSArray *dataArray = [BWJSONMatcher matchJSON:jsonString withClass:[TSCard class]];
You can using this method in JSONModel
NSError *error;
NSMutableArray <TSCard *> *yourArray = [TSCard arrayOfModelsFromString:strData error:&error];
and do your logic.
Iam Trying To map Json To Custom Object Called Place
Managed Object Class Of Place :
#interface Place : NSManagedObject
#property (nonatomic, retain) NSString * icon;
#property (nonatomic, retain) NSString * place_id;
#property (nonatomic, retain) NSString * name;
#property (nonatomic, retain) NSNumber * price_level;
#property (nonatomic, retain) NSNumber * rating;
#property (nonatomic, retain) NSString * vicinity;
#property (nonatomic, retain) NSString * reference;
#property (nonatomic, retain) Geometry *geometry;
#property (nonatomic, retain) Json *json;
#property (nonatomic, retain) NSSet *opening_hours;
#property (nonatomic, retain) NSSet *photos;
#property (nonatomic, retain) NSSet *types;
#end
and json in this formate :
"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" : "CnRoAAAAtHLK7ii6I9RN0soDFHF9Zqu1ppyHouUPu-E_BlAP2xlJJLMJrlsBBr3ALzYZ_ysFdgDzJOc-L3NkqQ2FLk5nOAW7LNldTthkSslmbXkXqGbScwCzAwgIj_EyUQlGQjS6d7Ng36nKy_SItlejfeR8zRIQYtT--IxV_d-GfdTcebDjfhoUU7gE_ufZOBxH35EPUtUXbCJk9Gs",
"width" : 1632
}
],
"price_level" : 2,
"rating" : 3.80,
"reference" : "CoQBcgAAAI_28BshREfmXJ9UKzOLLalhpRaqcW-Wupk1-D2sgkU6ZNe1nsR0zXopB5E-_BGXO1gHxJ1IAe0l-GXzrXj9Dz31crwQ-iwNFLcBRKSGnLmEu_AgKCkfDVZIsgeGrXLNxWLOZ_U8WAZzJu5Uc9tHa9LUF2Rj1MPk9vroGcFjLGWMEhCynlHHTt_P0EZ4wSwwfsumGhQAkqN53-D4ZNjBPEr7qJXZAZMdDg",
"types" : [ "cafe", "restaurant", "food", "establishment" ],
"vicinity" : "Harbourside Shopping Centre,Darling Harbour/227 & 229-230 Darling Drive, Sydney"
},
the problem when i try to map Photos,types
i have NSManagedObject Class For Photo
#interface Photo : NSManagedObject
#property (nonatomic, retain) NSNumber * height;
#property (nonatomic, retain) NSNumber * width;
#property (nonatomic, retain) NSString * photo_reference;
#property (nonatomic, retain) NSSet *html_attributions;
#property (nonatomic, retain) Place *place;
#end
i try to map this by :
RKEntityMapping* photosMapping = [RKEntityMapping mappingForEntityForName:NSStringFromClass([Photo class]) inManagedObjectStore:objectManager.managedObjectStore];
[photosMapping addAttributeMappingsFromArray:#[#"height",#"photo_reference",#"html_attributions",#"width"]];
//Add relationship between place and photos
[placeMapping addPropertyMapping:[RKRelationshipMapping relationshipMappingFromKeyPath:#"photos"
toKeyPath:#"photos"
withMapping:photosMapping]];
but there was exception Or value are photos is nil
how i can map photos and types any help please
You have two arrays of objects that aren't using KVC key paths, "html_attributions" and "types." See this RestKit article for more information about mapping in this type of situation: Mapping values without key paths
However -- if you have control over the JSON structure, I recommend creating two new Objective C classes, perhaps named HtmlAttribution and Type, each with one property, create mappings for those classes and set the relationships in RestKit. If you can do this and change how your JSON comes through, it will simplify things greatly for you.
Possible new JSON structure for those classes (snippets):
"html_attributions" : [ {"attribution_data":"\u003ca
href=\"https://plus.google.com/105663944571\u003c/a\u003e"} ],
"types" : [ {"type_name":"cafe"}, {"type_name":"restaurant"},
{"type_name":"food"}, {"type_name":"establishment"} ],