Search code examples
objective-ciosjsonjsonkit

How do I JSON serialize an NSDate Dictionary in JSONKit


I tried this using Jsonkit and Apple's JSON serializer with no luck. It keeps breaking on the geo property, which is an nsarray of NSNumbers.

Post* p = [[Post alloc] init];

    p.uname = @"mike";
    p.likes =[NSNumber numberWithInt:1];
    p.geo = [[NSArray alloc] initWithObjects:[NSNumber numberWithFloat:37.78583], [NSNumber numberWithFloat:-122.406417], nil ];
    p.place = @"New York City";
    p.caption = @"A test caption";
    p.date = [NSDate date];


 NSError* error = nil;

    NSString* stuff = [[p getDictionary] JSONStringWithOptions:JKParseOptionNone error:&error];

UPDATE: Checking on the error it's the NSDate that it fails on, not the NSArray. How do I pass in the date formatter into the function?

UPDATE 2: Solved- ok looked at the latest commit for jsonkit and saw that you could do this:

 NSDateFormatter *outputFormatter = [[NSDateFormatter alloc] init];
    [outputFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSSZZZ"];

    NSString* result = [p.dictionary JSONStringWithOptions:JKSerializeOptionNone serializeUnsupportedClassesUsingBlock:^id(id object) {
        if([object isKindOfClass:[NSDate class]]) { return([outputFormatter stringFromDate:object]); }
        return(nil);
    } error:nil];

which seems to have worked but note that this feature for JSONKit is WIP so it could change in the next official release.


Solution

  • Hmmmm -- can't speak for JSONKit or iOS5 -- I use Stig's SBJSON framework. Using it the implementation is fairly succinct:

    @implementation Post
    
    - (id) initWithName:(NSString*)Name :(NSNumber*)Likes :(NSArray*)Geo :(NSString*)Place :(NSString*)Caption :(NSDate*)Date {
    
       if ((self=[super init])==nil) {
           return nil;
       }
       uname = Name;
       likes = Likes;
       geo = Geo;
       place = Place;
       caption = Caption;
       date = Date;
       return self;
    }
    
    - (NSDictionary*) getAsDictionary {
       NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
       [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
       NSString *dateString = [dateFormatter stringFromDate:[NSDate date]];
       [dateFormatter release];
    
       NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:uname,@"uname",
                          likes,@"likes",
                          geo,@"geo",
                          place,@"place",
                          caption,@"caption",
                          dateString,@"date",
                          nil];
       return dict;
    }
    
    @end
    

    and

    - (void)viewDidLoad {
        [super viewDidLoad];
    
        Post* post = [[Post alloc] initWithName:@"Mike" 
                                           :[NSNumber numberWithInt:1] 
                                           :[[NSArray alloc] initWithObjects:[NSNumber numberWithFloat:37.78583], [NSNumber numberWithFloat:-122.406417],nil] 
                                           :@"New York City" :@"A Test caption" 
                                           :[NSDate date]];
    
        SBJsonWriter *writer = [[SBJsonWriter alloc] init];
        NSString* json = [writer stringWithObject:[post getAsDictionary]];
        if (json == nil) {
            NSLog(@"error = %@",writer.errorTrace);
        }
        NSLog(@"json = %@",json);
        [writer release];
        [post release];
    }
    

    produces

    TestJSON[52337:207] json = {"likes":1,"date":"2011-12-13 11:12:57","place":"New York City","caption":"A Test caption","uname":"Mike","geo":[37.78583,-122.4064]}