dchohfi / KeyValueObjectMapping

Automatic KeyValue Object Mapping for Objective-C, parse JSON/plist/Dictionary automatically
http://dchohfi.com/
MIT License
601 stars 90 forks source link

Support NSNull when converting NSDictionary/NSArray to Model #23

Open akinsella opened 11 years ago

akinsella commented 11 years ago

Hi,

I got some issues when converting NSDictionary / NSArray from JSONKit with DCKeyValueObjectMapping library because it does not support NSNull representation.

By default when a object is nil, JSONKit will use NSNull.

I fixed it in DCNSDateConverter, but there may be more cases.

1 - Data loader code (Loads Facebook repositories on GitHub)

Note: Some repositories don't have push date. In this case JSONKit sets NSNull in dictionary when deserializing the data.

AFHTTPClient *httpClient = [AFHTTPClient clientWithBaseURL:[NSURL URLWithString:@"https://api.github.com"]];
NSURLRequest *urlRequest = [httpClient requestWithMethod:@"GET" path:@"/orgs/facebook/repos" parameters:nil];

AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:urlRequest];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
    NSString *jsonString = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
    NSArray *json = [jsonString objectFromJSONString];

    DCParserConfiguration *parserConfiguration = [DCParserConfiguration configuration];
    parserConfiguration.datePattern = @"yyyy-MM-dd'T'HH:mm:ss'Z'";
    DCKeyValueObjectMapping *parser = [DCKeyValueObjectMapping mapperForClass: GHRepository.class andConfiguration:parserConfiguration];
    NSLog(@"Data loaded");
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"Error: %@", error);
}];

[operation start];

2 - GHRepository code

#import "GHOwner.h"

@interface GHRepository : NSObject

@property (nonatomic, strong) NSNumber *identifier;

@property (nonatomic, strong) NSNumber *forks;
@property (nonatomic, strong) NSString *full_name;
@property (nonatomic, strong) NSString *language;
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSNumber *open_issues;
@property (nonatomic, strong) NSString *url;
@property (nonatomic, strong) NSNumber *watchers;
@property (nonatomic, strong) NSDate *pushed_at;

@end

3 - Code to fix NSNull in DCNSDateConverter class

- (id)transformValue:(id)value forDynamicAttribute:(DCDynamicAttribute *)attribute {
    BOOL validDouble = [self validDouble:[NSString stringWithFormat:@"%@", value]];
    if(validDouble){
        return [NSDate dateWithTimeIntervalSince1970:[value doubleValue]];
    }else{
        NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
        formatter.dateFormat = self.pattern;
        /* Code to fix the issue here */
        if ([value isKindOfClass:NSNull.class]) {
            return nil;
        }
        return [formatter dateFromString:value];
    }
}
EsSpectacularrr commented 10 years ago

Also ran into this issue and had to add on NSNull checking in