25

I'm getting this exception when I try to JSON encode NSDate object.I believe NSDate is not compatible for JSON encoding. but I must encode the date.Any solutions?

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Invalid type in JSON write (__NSDate)'
Harikrishnan
  • 9,688
  • 11
  • 84
  • 127

8 Answers8

14

FIrst store your data in NSString. And then convert your string to NSDate.

You can refer SO:

Converting NSString to NSDate (and back again)

NSString to NSDate conversion problem

How to convert NSString to NSDate using NSDateFormatter?

Community
  • 1
  • 1
Rushi
  • 4,553
  • 4
  • 33
  • 46
  • 3
    This doesn't make sense. The OP is asking how to **encode** an NSDate. That means they should convert the NSDate to an NSString before inserting it into the dictionary they are attempting to JSON encode. My answer below shows an example solution. – sumizome Aug 04 '14 at 23:11
  • 2
    not a good solution. its just a by-pass. I need to know how to make it work with NSDate itself or, if not, why this is happening. – Nishant Jan 21 '15 at 17:06
7

Convert NSDate to NSString and try to encode.

- (NSString *) changeDateToDateString :(NSDate *) date {

    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setTimeZone:[NSTimeZone localTimeZone]];
    NSLocale *locale = [NSLocale currentLocale];
    NSString *dateFormat = [NSDateFormatter dateFormatFromTemplate:@"hh mm" options:0 locale:locale];
    [dateFormatter setDateFormat:dateFormat];
    [dateFormatter setLocale:locale];
    NSString *dateString = [dateFormatter stringFromDate:date];
    return dateString;
}
Ab'initio
  • 5,368
  • 4
  • 28
  • 40
pradeepa
  • 4,104
  • 5
  • 31
  • 41
5

As noted, you must first convert your NSDate to an NSString. It's not immediately clear, however, which format the date should be represented in. The answer can be found here: "JSON itself does not specify how dates should be represented, but Javascript does" -- ISO8601.

Here is an ISO8601 conversion method from a helper category for NSDate, courtesy Erica Sadun:

- (NSString *)ISO8601 {
    struct tm time;
    time_t interval = [self timeIntervalSince1970];
    gmtime_r(&interval, &time);
    char *x = calloc(1, 21);
    strftime_l(x, 20, "%FT%TZ", &time, gmtlocale);
    NSString *string = [NSString stringWithUTF8String:x];
    free(x);
    return string;
}

If you get an ISO8601 string back in a JSON payload and want to convert it to an NSDate, use this class method for NSDate:

+ (NSDate *)dateFromISO8601:(NSString *)string {
    if(!string) return nil;
    if (![string isKindOfClass:[NSString class]]) return nil;
    struct tm time;
    strptime_l([string UTF8String], "%FT%TZ", &time, gmtlocale);
    return [NSDate dateWithTimeIntervalSince1970:timegm(&time)];
}
Community
  • 1
  • 1
sumizome
  • 712
  • 8
  • 11
4

Have you tried ?

updateDate = [NSNumber numberWithFloat:[[NSDate date] timeIntervalSince1970]];

As Described Here : SDK not supporting NSDate objects

Follow these Steps :

1. Convert the Date in JSON Format :

 NSDateFormatter *formatter = [[[NSDateFormatter alloc] init]autorelease];
 [formatter setDateFormat:@"Z"];
 NSString *updateDate = [NSString stringWithFormat:@"/Date(%.0f000%@)/", [[NSDate date] timeIntervalSince1970],[formatter stringFromDate:[NSDate date]]];

2. Embed In some array and POST the array.

iosMentalist
  • 3,066
  • 1
  • 30
  • 40
Bhavin
  • 27,155
  • 11
  • 55
  • 94
  • 3
    Why on earth would you be using float? float has 24 bit precisions. There's over a billion seconds since 1970. Which means your resolution is worse than a minute. Your date format is absolutely non-standard. – gnasher729 Jul 28 '14 at 07:44
2

The simplest way to store and retrieve a NSDate object in JSON would be to use the timeIntervalSince1970 property of NSDate.

The returned NSTimeInterval (double) is pretty standard and can easily be converted back to a NSDate object using:

NSDate dateWithTimeIntervalSince1970:<#(NSTimeInterval)#>
Julius
  • 1,005
  • 1
  • 9
  • 19
1

You must convert the date to a string before you try to encode it. There are enough examples everywhere so it should be easy to find

Ismael
  • 3,927
  • 3
  • 15
  • 23
0

For our case, we are using Mantle to convert an object to JSON and one of our objects with property NSDate is missing its JSONTransformer

@property (nonatomic) NSDate *expiryDate;

where:

+ (NSValueTransformer *)expiryDateJSONTransformer {
     return [MTLValueTransformer transformerUsingForwardBlock:^id(NSString *dateString, BOOL *success, NSError *__autoreleasing *error) {
        return [self.dateFormatter dateFromString:dateString];
    } reverseBlock:^id(NSDate *date, BOOL *success, NSError *__autoreleasing *error) {
        return [self.dateFormatter stringFromDate:date];
    }];
}

+ (NSDateFormatter *)dateFormatter {
    NSDateFormatter *df = [NSDateFormatter new];
    df.dateFormat = @"yyyy-MM-dd";
    return df;
}
Ted
  • 22,696
  • 11
  • 95
  • 109
0

I am doing something like this in my body params encoder

// handle dates
              var _params = [String: Any]()
              params.forEach { (key, value) in
                if let date = value as? Date {
                    _params[key] = DateFormatter.iso8601Full.string(from: date)
                } else {
                    _params[key] = value
                }
              }

              return try? JSONSerialization.data(withJSONObject: _params)
Michał Ziobro
  • 10,759
  • 11
  • 88
  • 143