Skip to content

Instantly share code, notes, and snippets.

@tapi
Created April 25, 2012 11:37
Show Gist options
  • Save tapi/2489095 to your computer and use it in GitHub Desktop.
Save tapi/2489095 to your computer and use it in GitHub Desktop.
Dictionary <--> Object Mapper for Objective-C
//
// NSObject+SMDictionaryMapping.h
// SoundTrack
//
// Created by Paddy O'Brien on 12-04-24.
// Copyright (c) 2012 Paddy O'Brien. All rights reserved.
//
#import <Foundation/Foundation.h>
@protocol SMMappedObject <NSObject>
+ (NSDictionary *)mappedKeys;
@end
@interface NSObject (SMDictionaryMapping)
- (id)initWithDictionary:(NSDictionary *)dictionary;
- (void)updateWithDictionary:(NSDictionary *)dictionary;
@end
//
// NSObject+DictionaryMapping.m
// SoundTrack
//
// Created by Paddy O'Brien on 12-04-24.
// Copyright (c) 2012 Paddy O'Brien. All rights reserved.
//
#import "NSObject+DictionaryMapping.h"
@interface NSObject ()
- (void)mapDictionaryToProperties:(NSDictionary *)dictionary;
@end
@implementation NSObject (DictionaryMapping)
- (id)initWithDictionary:(NSDictionary *)dictionary
{
if (self) {
[self mapDictionaryToProperties:dictionary];
}
return self;
}
- (void)updatePropertiesWithDictionary:(NSDictionary *)dictionary
{
[self mapDictionaryToProperties:dictionary];
}
- (void)mapDictionaryToProperties:(NSDictionary *)dictionary
{
NSArray* keys = [dictionary allKeys];
for (NSString *key in keys) {
NSString *mappedKey = key;
if ([self conformsToProtocol:@protocol(SMMappedObject)] && [self respondsToSelector:@selector(mappedKeys)]) {
NSDictionary *mappedKeys = [self performSelector:@selector(mappedKeys)];
if ([mappedKeys valueForKey:key]) {
mappedKey = [mappedKeys valueForKey:key];
}
}
[self setValue:[dictionary valueForKey:key] forKey:mappedKey];
}
}
@end
//
// NSObject+SMDictionaryMapping.h
//
// Created by Paddy O'Brien on 12-04-24.
// Copyright (c) 2012 Paddy O'Brien. All rights reserved.
//
#import <Foundation/Foundation.h>
@protocol SMMappedObject <NSObject>
+ (NSDictionary *)mappedKeys;
@end
@interface NSObject (SMDictionaryMapping)
- (id)initWithDictionary:(NSDictionary *)dictionary;
- (void)updateWithDictionary:(NSDictionary *)dictionary;
@end
//
// NSObject+DictionaryMapping.m
//
// Created by Paddy O'Brien on 12-04-24.
// Copyright (c) 2012 Paddy O'Brien. All rights reserved.
//
#import "NSObject+DictionaryMapping.h"
@interface NSObject ()
- (void)mapDictionaryToProperties:(NSDictionary *)dictionary;
@end
@implementation NSObject (DictionaryMapping)
- (id)initWithDictionary:(NSDictionary *)dictionary
{
if (self) {
[self mapDictionaryToProperties:dictionary];
}
return self;
}
- (void)updatePropertiesWithDictionary:(NSDictionary *)dictionary
{
[self mapDictionaryToProperties:dictionary];
}
- (void)mapDictionaryToProperties:(NSDictionary *)dictionary
{
NSArray* keys = [dictionary allKeys];
for (NSString *key in keys) {
NSString *mappedKey = key;
if ([self conformsToProtocol:@protocol(SMMappedObject)] && [self respondsToSelector:@selector(mappedKeys)]) {
NSDictionary *mappedKeys = [self performSelector:@selector(mappedKeys)];
if ([mappedKeys valueForKey:key]) {
mappedKey = [mappedKeys valueForKey:key];
}
}
id value = ([[dictionary valueForKey:key] isKindOfClass:[NSNull class]]) ? nil : [dictionary valueForKey:key];
[self setValue:value forKey:mappedKey];
}
}
@end
@aaronpeterson
Copy link

I'm curious about sub-entities and arrays of sub-entities, too. Would it be best to define those in the model class as an array of strings (JSON key names) you want explicitly mapped to sub-entities? One thing all of my JSON keys have in common is that the sub-entity keys are all upper-case first character. This could be the "auto" mode; if a mapped key is upper-case first character it looks for a model class of same name and maps accordingly. I haven't looked to see what something like RestKit does. Just seems like something that could be a single NSObject category rather than a giant library.

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