/
NSObject+JTObjectMapping.m
102 lines (89 loc) · 4.5 KB
/
NSObject+JTObjectMapping.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
//
// NSObject+JTObjectMapping.m
// JTObjectMapping
//
// Created by james on 9/6/11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#import "NSObject+JTObjectMapping.h"
#import "JTMappings.h"
#import "JTDateMappings.h"
#import <objc/runtime.h>
@implementation NSObject (JTObjectMapping)
- (void)setValueFromDictionary:(NSDictionary *)dict mapping:(NSDictionary *)mapping {
[dict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
id mapsToValue = [mapping objectForKey:key];
if (mapsToValue == nil) {
// We wants to auto reference the NSDictionary key corresponding NSObject property key
// with the same name defined as in the NSObject subclass.
if ([[self class] instancesRespondToSelector:NSSelectorFromString(key)]) {
mapsToValue = key;
}
}
if (mapsToValue != nil) {
if ([(NSObject *)mapsToValue isKindOfClass:[NSString class]]) {
if ([obj isKindOfClass:[NSNull class]]) {
[self setValue:nil forKey:mapsToValue];
} else {
[self setValue:obj forKey:mapsToValue];
}
} else if ([mapsToValue conformsToProtocol:@protocol(JTMappings)] && [(NSObject *)obj isKindOfClass:[NSDictionary class]]) {
id <JTMappings> mappings = (id <JTMappings>)mapsToValue;
NSObject *targetObject = [[mappings.targetClass alloc] init];
[targetObject setValueFromDictionary:obj mapping:mappings.mapping];
[self setValue:targetObject forKey:mappings.key];
[targetObject release];
} else if ([mapsToValue conformsToProtocol:@protocol(JTDateMappings)] && [(NSObject *)obj isKindOfClass:[NSString class]]) {
id <JTDateMappings> mappings = (id <JTDateMappings>)mapsToValue;
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:mappings.dateFormatString];
NSDate *date = [formatter dateFromString:obj];
[formatter release];
[self setValue:date forKey:mappings.key];
} else if ([(NSObject *)obj isKindOfClass:[NSArray class]]) {
if ([mapsToValue conformsToProtocol:@protocol(JTMappings)]) {
id <JTMappings> mappings = (id <JTMappings>)mapsToValue;
NSObject *object = [mappings.targetClass objectFromJSONObject:obj mapping:mappings.mapping];
[self setValue:object forKey:mappings.key];
} else {
NSMutableArray *array = [NSMutableArray array];
for (NSObject *o in obj) {
[array addObject:o];
}
[self setValue:[NSArray arrayWithArray:array] forKey:mapsToValue];
}
} else {
NSAssert2(NO, @"[mapsToValue class]: %@, [obj class]: %@ is not handled", NSStringFromClass([mapsToValue class]), NSStringFromClass([obj class]));
}
}
}];
}
+ (id <JTMappings>)mappingWithKey:(NSString *)key mapping:(NSDictionary *)mapping {
return [JTMappings mappingWithKey:key targetClass:[self class] mapping:mapping];
}
+ (id)objectFromJSONObject:(id<JTValidJSONResponse>)object mapping:(NSDictionary *)mapping {
id returnObject = nil;
if ([object isKindOfClass:[NSDictionary class]]) {
returnObject = [[[[self class] alloc] init] autorelease];
[returnObject setValueFromDictionary:(NSDictionary *)object mapping:mapping];
} else if ([object isKindOfClass:[NSArray class]]) {
NSMutableArray *array = [NSMutableArray array];
for (NSObject *dict in (NSArray *)object) {
NSParameterAssert([dict isKindOfClass:[NSDictionary class]]);
NSObject *newObj = [[self class] objectFromJSONObject:(NSDictionary *)dict mapping:mapping];
[array addObject:newObj];
}
returnObject = [NSArray arrayWithArray:array];
}
return returnObject;
}
@end
@implementation NSDate (JTObjectMapping)
+ (id <JTMappings>)mappingWithKey:(NSString *)key mapping:(NSDictionary *)mapping {
[NSException raise:@"JTObjectMappingException" format:@"Please use +[NSDate mappingWithKey:dateFormatString:] instead."];
return nil;
}
+ (id <JTDateMappings>)mappingWithKey:(NSString *)key dateFormatString:(NSString *)dateFormatString {
return [JTDateMappings mappingWithKey:key dateFormatString:dateFormatString];
}
@end