Created
December 17, 2013 17:41
-
-
Save NavidMitchell/8009299 to your computer and use it in GitHub Desktop.
Json to Objective-c un-marshaller
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// THXDictionaryMapper.m | |
// Spark | |
// | |
// Created by Navid Mitchell on 6/19/13. | |
// Copyright (c) 2013 Navid Mitchell. All rights reserved. | |
// | |
#import "THXDictionaryMapper.h" | |
#import "objc/runtime.h" | |
#import "THXSparkDateFormatter.h" | |
@implementation THXDictionaryMapper | |
@synthesize propertyReplacement = _propertyReplacement; | |
-(NSDictionary *)convertObject:(id)object{ | |
NSMutableDictionary *results = [[NSMutableDictionary alloc] init]; | |
NSArray *properties = [self getPropertyNames:[object class]]; | |
for (NSString *propertyName in properties) { | |
id value = [object valueForKey:propertyName]; | |
value = [self convertValue:value]; | |
if(value == nil){ | |
value = [[NSNull alloc]init]; | |
} | |
[results setObject:value forKey:[self convertName:propertyName]]; | |
} | |
return results; | |
} | |
-(NSArray *)convertArray:(NSArray *)array{ | |
NSMutableArray *ret = [[NSMutableArray alloc]init]; | |
for (id i in array){ | |
[ret addObject:[self convertValue:i]]; | |
} | |
return ret; | |
} | |
-(id)convertValue:(id)value{ | |
if([self shouldExpand:value]){ | |
value = [self convertObject:value]; | |
}else if([value isKindOfClass:[NSArray class]]){ | |
value = [self convertArray:value]; | |
} else if ([value isKindOfClass:[NSDate class]]) { | |
value = [self stringFromDate:value]; | |
} | |
return value; | |
} | |
-(NSString*)convertName:(NSString *)name{ | |
NSString *ret = name; | |
if(_propertyReplacement != nil){ | |
ret = [_propertyReplacement objectForKey:name]; | |
if(ret == nil){ | |
ret = name; | |
} | |
} | |
return ret; | |
} | |
-(Boolean)shouldExpand:(id)object{ | |
Boolean ret = NO; | |
if(object != nil | |
&& ![object isKindOfClass:[NSArray class]] | |
&& ![object isKindOfClass:[NSDate class]] | |
&& ![object isKindOfClass:[NSNumber class]] | |
&& ![object isKindOfClass:[NSString class]]){ | |
ret = YES; | |
} | |
return ret; | |
} | |
/** | |
* Returns all property names for the given class and its superclasses. | |
*/ | |
-(NSArray *)getPropertyNames:(Class)clazz{ | |
NSMutableArray *ret = [[NSMutableArray alloc]init]; | |
unsigned int outCount, i; | |
objc_property_t *properties = class_copyPropertyList(clazz, &outCount); | |
for (i = 0; i < outCount; i++) { | |
objc_property_t property = properties[i]; | |
const char *propName = property_getName(property); | |
if(propName) { | |
//** Not used now but if we wanted a type as well this could be used | |
// const char *propType = getPropertyType(property); | |
// NSString *propertyType = [NSString stringWithUTF8String:propType]; | |
NSString *propertyName = [NSString stringWithUTF8String:propName]; | |
[ret addObject:propertyName]; | |
} | |
} | |
free(properties); | |
clazz = class_getSuperclass(clazz); | |
if(clazz != nil){ | |
NSString *className = [NSString stringWithUTF8String:class_getName(clazz)]; | |
if(![className isEqualToString:@"NSObject"]){ | |
[ret addObjectsFromArray:[self getPropertyNames:clazz]]; | |
} | |
} | |
return ret; | |
} | |
-(NSString *)stringFromDate:(NSDate *)date{ | |
THXSparkDateFormatter *formatter = [[THXSparkDateFormatter alloc]init]; | |
return [formatter stringFromDate:date]; | |
} | |
//*** Currently not used. Left here for ref in case we want to cache "Mapping Paths" | |
static const char * getPropertyType(objc_property_t property) { | |
const char *attributes = property_getAttributes(property); | |
printf("attributes=%s\n", attributes); | |
char buffer[1 + strlen(attributes)]; | |
strcpy(buffer, attributes); | |
char *state = buffer, *attribute; | |
while ((attribute = strsep(&state, ",")) != NULL) { | |
if (attribute[0] == 'T' && attribute[1] != '@') { | |
// it's a C primitive type: | |
/* | |
if you want a list of what will be returned for these primitives, search online for | |
"objective-c" "Property Attribute Description Examples" | |
apple docs list plenty of examples of what you get for int "i", long "l", unsigned "I", struct, etc. | |
*/ | |
return (const char *)[[NSData dataWithBytes:(attribute + 1) length:strlen(attribute) - 1] bytes]; | |
} | |
else if (attribute[0] == 'T' && attribute[1] == '@' && strlen(attribute) == 2) { | |
// it's an ObjC id type: | |
return "id"; | |
} | |
else if (attribute[0] == 'T' && attribute[1] == '@') { | |
// it's another ObjC object type: | |
return (const char *)[[NSData dataWithBytes:(attribute + 3) length:strlen(attribute) - 4] bytes]; | |
} | |
} | |
return ""; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment