Edited at

Core Dataを JSON形式で取り出す

More than 5 years have passed since last update.


はじめに

Core DataをJSON形式でエクスポートしたかったんですが、いい情報がなかったので実装してみました。とりあえずの実装なので、もっと短くスマートにかけるのでどんどんいじって使ってください。

NSManagedObjectのプロパティがint、floatになることは無いので、不要な部分が多いですが別の機会に使えそうなのであえて残してあります。


コード

    NSMutableArray *mutableFetchResults = [[context executeFetchRequest:request error:nil] mutableCopy];

if (mutableFetchResults == nil) {
NSLog(@"no results");
}
NSMutableArray *marray = [NSMutableArray array];

for(id tmpEntity in mutableFetchResults){
NSMutableDictionary *tmpDict = [NSMutableDictionary dictionary];
unsigned int count;
objc_property_t* props = class_copyPropertyList([tmpEntity class], &count);
for (int i = 0; i < count; i++) {
objc_property_t property = props[i];
const char * name = property_getName(property);
NSString *propertyName = [NSString stringWithCString:name encoding:NSUTF8StringEncoding];
const char * type = property_getAttributes(property);
NSString *attr = [NSString stringWithCString:type encoding:NSUTF8StringEncoding];
NSString * typeString = [NSString stringWithUTF8String:type];
NSArray * attributes = [typeString componentsSeparatedByString:@","];
NSString * typeAttribute = [attributes objectAtIndex:0];
NSString * propertyType = [typeAttribute substringFromIndex:1];
const char * rawPropertyType = [propertyType UTF8String];

if (strcmp(rawPropertyType, @encode(float)) == 0) {
//it's a float
float tmpValue = [[tmpEntity valueForKey:propertyName] floatValue];
NSString *value = [NSString stringWithFormat:@"%f",tmpValue];
[tmpDict setObject:value forKey:propertyName];
} else if (strcmp(rawPropertyType, @encode(int)) == 0) {
//it's an int
int tmpValue = [[tmpEntity valueForKey:propertyName] intValue];
NSString *value = [NSString stringWithFormat:@"%d",tmpValue];
[tmpDict setObject:value forKey:propertyName];
} else if (strcmp(rawPropertyType, @encode(id)) == 0) {
//it's some sort of object
} else {
// According to Apples Documentation you can determine the corresponding encoding values
}

if ([typeAttribute hasPrefix:@"T@"]) {
NSString * typeClassName = [typeAttribute substringWithRange:NSMakeRange(3, [typeAttribute length]-4)]; //turns @"NSDate" into NSDate
Class typeClass = NSClassFromString(typeClassName);
if (typeClass != nil) {
// Here is the corresponding class even for nil values
if(typeClass == [NSString class]){
NSString *string = [tmpEntity valueForKey:propertyName];
if(string == nil)continue;
[tmpDict setObject:string forKey:propertyName];

}else if(typeClass ==[NSDate class]){
NSDate *date = [tmpEntity valueForKey:propertyName];
if(date == nil)continue;
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss zzz"];
[formatter setTimeZone:[NSTimeZone timeZoneWithName:@"Asia/Tokyo"]];
NSString *stringFromDate = [formatter stringFromDate:date];
[tmpDict setObject:stringFromDate forKey:propertyName];
}else if(typeClass == [NSNumber class]){
NSNumber *number = [tmpEntity valueForKey:propertyName];
if(number == nil)continue;
NSString *stringFromNum = [number stringValue];
[tmpDict setObject:stringFromNum forKey:propertyName];
}
}
}

}
[marray addObject:tmpDict];
free(props);
}

NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:marray
options:NSJSONWritingPrettyPrinted // Pass 0 if you don't care about the readability of the generated string
error:&error];

if (! jsonData) {
NSLog(@"Got an error: %@", error);
} else {
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
}