Object Mapping library from JSON to NSObjects

前端 未结 5 1927
别那么骄傲
别那么骄傲 2021-02-04 08:39

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

5条回答
  •  慢半拍i
    慢半拍i (楼主)
    2021-02-04 08:58

    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 */) {
                    // ...
                }
            }
        }
        // ...
    }
    

提交回复
热议问题