Skip to content

Instantly share code, notes, and snippets.

@k0nserv
Created November 4, 2014 19:42
Show Gist options
  • Save k0nserv/42c2aa2c6c4d8c7202cd to your computer and use it in GitHub Desktop.
Save k0nserv/42c2aa2c6c4d8c7202cd to your computer and use it in GitHub Desktop.
//
// HTKVOMappingStrategy.h
//
// Created by Hugo Tunius on 16/02/14.
// Copyright (c) 2014 Hugo Tunius. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "HTMappingStrategy.h"
@interface HTKVCMappingStrategy : NSObject <HTMappingStrategy>
+ (id)defaultKVCStrategy;
- (void)overrideProperty:(NSString *)property toKVPath:(NSString *)path;
- (id)mapModel:(Class)model withData:(NSDictionary *)data;
@end
//
// HTKVOMappingStrategy.m
//
// Created by Hugo Tunius on 16/02/14.
// Copyright (c) 2014 Hugo Tunius. All rights reserved.
//
#import "HTKVCMappingStrategy.h"
#import "NSString+Sanitize.h"
@interface HTKVCMappingStrategy ()
@property(nonatomic, readonly, strong) NSMutableDictionary *overridenMappings;
@end
@implementation HTKVCMappingStrategy
@synthesize overridenMappings = _overridenMappings;
- (NSMutableDictionary *)overridenMappings {
if (!_overridenMappings) {
_overridenMappings = [[NSMutableDictionary alloc] init];
}
return _overridenMappings;
}
+ (id)defaultKVCStrategy {
return [[[self class] alloc] init];
}
- (void)overrideProperty:(NSString *)property toKVPath:(NSString *)path {
[self.overridenMappings setObject:path forKey:property];
}
- (id)mapModel:(Class)model withData:(NSDictionary *)data {
id result = [[model alloc] init];
for (NSString *key in data.allKeys) {
NSString *KVPath;
if ([self.overridenMappings objectForKey:key] != nil) {
KVPath = [self.overridenMappings objectForKey:key];
} else {
KVPath = [key snakeCaseToCamelCase];
}
[result setValue:data[key] forKey:KVPath];
}
return result;
}
@end
//
// HTMappingStrategy.h
//
// Created by Hugo Tunius on 16/02/14.
// Copyright (c) 2014 Hugo Tunius. All rights reserved.
//
#import <Foundation/Foundation.h>
@protocol HTMappingStrategy <NSObject>
@required
- (id)mapModel:(Class)model withData:(NSDictionary *)data;
@end
//
// HTModelJSONMapper.h
//
// Created by Hugo Tunius on 16/02/14.
// Copyright (c) 2014 Hugo Tunius. All rights reserved.
//
#import <Foundation/Foundation.h>
@class HTKVCMappingStrategy;
@interface HTModelJSONMapper : NSObject
- (BOOL)validObjects:(NSArray *)array;
- (BOOL)validObject:(NSDictionary *)data;
- (void)mapKind:(NSString *)kind toModel:(Class)model withMappingStrategy:(HTKVCMappingStrategy *)strategy;
- (id)createObjectWithData:(NSDictionary *)data;
- (NSArray *)createObjectsWithData:(NSArray *)data;
@end
//
// HTModelJSONMapper.m
//
// Created by Hugo Tunius on 16/02/14.
// Copyright (c) 2014 Hugo Tunius. All rights reserved.
//
#import "HTModelJSONMapper.h"
#import "HTMappingStrategy.h"
static NSString *const kKindKey = @"kind";
static NSString *const kClassKey = @"class";
static NSString *const kStrategyKey = @"strategy";
@interface HTModelJSONMapper ()
@property(nonatomic, copy, readonly) NSMutableDictionary *mappings;
@end
@implementation HTModelJSONMapper
@synthesize mappings = _mappings;
- (NSMutableDictionary *)mappings {
if (_mappings == nil) {
_mappings = [[NSMutableDictionary alloc] init];
}
return _mappings;
}
- (BOOL)validObjects:(NSArray *)array {
if (array.count == 0) {
return NO;
}
id firstObject = [array firstObject];
if ([firstObject isKindOfClass:[NSDictionary class]]) {
return [self validObject:firstObject];
}
return NO;
}
- (BOOL)validObject:(NSDictionary *)data {
NSString *kind = [data objectForKey:kKindKey];
if (kind == nil) {
return NO;
}
return [self.mappings objectForKey:kind] != nil;
}
- (void)mapKind:(NSString *)kind toModel:(Class)model withMappingStrategy:(HTKVCMappingStrategy *)strategy {
NSDictionary *existing = [self.mappings objectForKey:kind];
if (existing != nil) {
[NSException raise:@"Mapping already exists." format:@"A mapping already exists for kind %@", kind];
}
NSDictionary *value = @{ kClassKey : model, kStrategyKey : strategy };
[self.mappings setObject:value forKey:kind];
}
- (id)createObjectWithData:(NSDictionary *)data {
NSMutableDictionary *resultData = [[NSMutableDictionary alloc] init];
NSString *kind = [data objectForKey:kKindKey];
if (kind == nil) {
[NSException raise:@"Kind value missing in data" format:nil];
}
NSDictionary *mappingStrategyDetails = [self.mappings objectForKey:kind];
if (mappingStrategyDetails == nil) {
[NSException raise:@"No mapping strategy found" format:@"No strategy could be found for %@", kind];
}
for (NSString *key in data.allKeys) {
id subData = [data objectForKey:key];
if ([subData isKindOfClass:[NSDictionary class]]) {
NSDictionary *subData = [data objectForKey:key];
if ([subData objectForKey:kKindKey]) {
id object = [self createObjectWithData:subData];
[resultData setObject:object forKey:key];
}
} else if ([subData isKindOfClass:[NSArray class]]) {
} else {
[resultData setObject:subData forKey:key];
}
}
id<HTMappingStrategy> strategy = (id<HTMappingStrategy>)[mappingStrategyDetails objectForKey:kStrategyKey];
Class modelClass = [mappingStrategyDetails objectForKey:kClassKey];
return [strategy mapModel:modelClass withData:[resultData copy]];
}
- (NSArray *)createObjectsWithData:(NSArray *)data {
if ([self validObjects:data]) {
NSMutableArray *array = [[NSMutableArray alloc] init];
for (NSDictionary *dict in data) {
[array addObject:[self createObjectWithData:dict]];
}
return [array copy];
}
return data;
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment