Skip to content

Instantly share code, notes, and snippets.

@void-main
Created May 1, 2014 13:38
Show Gist options
  • Save void-main/073677b6b390a6433a2b to your computer and use it in GitHub Desktop.
Save void-main/073677b6b390a6433a2b to your computer and use it in GitHub Desktop.
VMJsonableObject helps developer to easily fill an NSObject with NSDictionary (probably parsed from a JSON string).
// For example, let's define a VMUser class that saves user login info.
// VMUser.h
@interface VMUser : VMJsonableObject
@property (nonatomic)NSString *userId;
@property (nonatomic)NSString *userName;
@property (nonatomic)NSString *email;
@end
// VMUser.m
// Note the implementation part of `VMUser.m` file is empty.
// You only needs to write logic-related code now. YAY.
@implementation VMUser
@end
// And in the method you want to use it
id object = [NSJSONSerialization
JSONObjectWithData:serverResponseData
options:0
error:nil];
if([object isKindOfClass:[NSDictionary class]]) {
NSDictionary *results = (NSDictionary *)object;
VMUser *user = [[VMUser alloc] initWithDictionary:results];
NSLog(@"Login: %@", user.userName);
}
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
@interface VMJsonableObject : NSObject
- (id)initWithDictionary:(NSDictionary *)dictionary;
@end
#import "VMJsonableObject.h"
@implementation VMJsonableObject
- (id)initWithDictionary:(NSDictionary *)dictionary
{
if (self = [super init]) {
[self fillValues:dictionary];
}
return self;
}
// This is problem oriented method. Please change to match your own situation.
// In my case, the API property is `user_id` while the property name is `userId`
// If your json property name is exactly as your property name, simply return it.
// Otherwise, do whatever it takes to make them match.
- (NSString *)convertToJSONName:(NSString *)propertyName
{
// Step 1: find all (unique) uppercase characters
NSArray *occurrences = [propertyName componentsSeparatedByCharactersInSet:[[NSCharacterSet uppercaseLetterCharacterSet] invertedSet]];
NSSet *uniqueUppercaseCharacters = [NSSet setWithArray:occurrences];
// Step 2: replace the uppercase letters with format of `_[lowercase]`
for (NSString *uppercaseCharacter in uniqueUppercaseCharacters) {
propertyName = [propertyName stringByReplacingOccurrencesOfString:uppercaseCharacter
withString:[NSString stringWithFormat:@"_%@", [uppercaseCharacter lowercaseString]]];
}
return propertyName;
}
// Fill object with parsed dictionary from JSON string.
// This method uses runtime support provided by Objective-C.
// The advantage is quite obvious. It literally makes the function smaller.
- (void)fillValues:(NSDictionary *)dictionary
{
NSString *className = NSStringFromClass([self class]);
id curClass = objc_getClass([className UTF8String]);
unsigned int outCount, i;
objc_property_t *properties = class_copyPropertyList(curClass, &outCount);
for (i = 0; i < outCount; i++) {
objc_property_t property = properties[i];
NSString *propertyName = [NSString stringWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
id value = [dictionary objectForKey:[self convertToJSONName:propertyName]];
if (value) {
[self setValue:value forKey:propertyName];
}
}
}
@end
@lightxue
Copy link

lightxue commented Jun 6, 2014

f**king cool!!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment