I am trying to build a parser/objectMapper that will build Objective C objects for the JSON I consume from a REST service.
I took some inspiration from RestKit by having
Why not add mappings for classes?
+ (NSDictionary *)mapClasses {
return @{
@"category": [Category class],
// ...
};
}
For non-container properties, you could even do runtime introspection of properties to avoid redundant mappings.
Container properties could map to special wrapper objects:
[OMContainer arrayWithClass:Key.class], @"keys",
[OMContainer dicionaryWithKeyClass:ScopeID.class valueClass:Scope.class], @"possibleScopes",
Or even blocks for dynamic selection of types:
[OMDynamicType typeWithBlock:^(id obj){
if ([obj isKindOfClass:NSString.class] && [obj hasPrefix:@"foo"])
return Foo.class;
else
return Bar.class;
}], @"foo",
Implementing this could go something like:
+ (NSArray *)parseData:(NSData*)jsonData intoObjectsOfType:(Class)objectClass {
NSArray *parsed = /* ... */
NSMutableArray *decoded = [NSMutableArray array];
for (id obj in parsed) {
[decoded addObject:[self decodeRawObject:parsed intoObjectOfType:objectClass]];
}
return decoded;
}
+ (id)decodeRawObject:(NSDictionary *)dict intoObjectOfType:(Class)objectClass {
// ...
NSDictionary *jsonKeys = objectClass.mapProperties;
NSDictionary *jsonClasses = objectClass.mapClasses;
for (NSString *key in jsonKeys.allKeys) {
NSString *objectProperty = jsonKeys[key];
NSString *value = dict[key];
if (value) {
id klass = jsonClasses[key];
if (!klass) {
[entity setValue:value forKey:objectProperty];
} else if (klass == klass.class) {
[entity setValue:[self decodeRawObject:value intoObjectOfType:klass]
forKey:objectProperty];
} else if (/* check for containers and blocks */) {
// ...
}
}
}
// ...
}