Reputation: 2684
I am trying to parse a json string straight into a managed object. The json string contains all strings, but my Entity has Date objects.
if this is my json string
{
"name":"John",
"dob": "12/12/2008",
etc...
}
and here's my entity Person:
name : NSString
dob: Date
etc...
I want to parse that json straight through by looping through the keys of the Json dict, and setting the values to the matching keys of my entity:
Person *aPerson = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:managedObjectContext];
NSArray *keys = [jsonDict allKeys];
for (NSString *key in keys) {
[aPerson setValue:[jsonDict valueForKey:key] forKey:key];
}
This only works if all my entity's properties are NSStrings.
How can I get the type/class of my entity's property to be able to set the various types?
eg. if key = @"dob" how can I get the type/class of aPerson.dob?
so my code will look something like:
Person *aPerson = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:managedObjectContext];
NSArray *keys = [jsonDict allKeys];
for (NSString *key in keys) {
if([[aPerson objectForKey:key] isKindOfClass:[NSDate class]])
{
// Create an NSDate object
}else{
[aPerson setValue:[jsonDict valueForKey:key] forKey:key];
}
}
thanks
UPDATE:
Ok I tried using the isKindOfClass and here's the result was:
// for key = @"name"
// aPerson.name is NSString
[[aPerson valueForKey:key] isKindOfClass:[NSString class]] => TRUE
[[aPerson valueForKey:key] isKindOfClass:[NSObject class]] => TRUE
// for key = @"age"
// aPerson.age is NSNumber
[[aPerson valueForKey:key] isKindOfClass:[NSNumber class]] => TRUE
[[aPerson valueForKey:key] isKindOfClass:[NSObject class]] => TRUE
// for key = @"dob"
// aPerson.dob is NSDate
[[aPerson valueForKey:key] isKindOfClass:[NSDate class]] => FALSE
[[aPerson valueForKey:key] isKindOfClass:[NSObject class]] => FALSE
how is that? @dynamic dob and NSDate, is notOfClass NSDate!
please tell me what I am missing!
Upvotes: 1
Views: 4127
Reputation: 1318
I know, this is a late answer, but as I was search today for a good solution... This is what I'm using now:
NSEntityDescription * myEntity = [object entity];
NSDictionary * attributes = [myEntity attributesByName];
if ([[[attributes objectForKey:key] attributeValueClassName] isEqualToString:@"NSDate"]) {
// this type is NSDate
}
Hope this helps :)
Upvotes: 3
Reputation: 2684
Thanks a lot to Rog, for sending me in the right direction, I ended up overriding my setter as below:
-(void)setDob:(id)value
{
[self willAccessValueForKey:@"dob"];
if ([value isKindOfClass:[NSString class]]) {
[self setPrimitiveValue:[DateFormatter dateFromString:value] forKey:@"dob"];
}else{
[self setPrimitiveValue:value forKey:@"dob"];
}
[self didChangeValueForKey:@"dob"];
}
and all works great now, instead of a 1000 lines of code parsing, it's all done in 3! nice one!
Upvotes: 0
Reputation: 18670
You can either convert your JSON string to NSDate and then assign it to your NSManagedObject, or you can create a custom setter in your Person class that takes an NSString and returns NSDate. Here's an example:
- (NSDate*)convertStringToDate:(NSString*)dateString {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
// this is imporant - we set our input date format to match our input string
// if format doesn't match you'll get nil from your string, so be careful
[dateFormatter setDateFormat:@"d MMMM yyyy"];
NSDate *dateFromString = [dateFormatter dateFromString:dateString];
[dateFormatter release];
return dateFromString;
}
Upvotes: 1