我正在使用Stig Brautaset的JSON框架序列化一些对象,包括NSDates(不直接支持)。
我决定使用NSDate的描述作为日期的JSONFragment表示(我不关心这样做会导致精确度的轻微损失)。
为了扩展Stig Brautaset的JSON框架以包含NSDates,我定义了一个类别:
@interface NSDate (NSDate_JSON) <JSONInitializer>
-(NSString *) JSONFragment;
@end
要从JSON重新创建NSDate(和其他类),我使用以下初始化程序定义了一个协议:
@protocol JSONInitializer <NSObject>
-(id) initWithJSONRepresentation: (NSString *) aJSONRepresentation;
@end
我遇到了这个初始化程序的问题。在NSDate的情况下,它只调用initWithString:,这就是我遇到麻烦:它总是返回nil。这是实施:
#import "NSDate+JSON.h"
@implementation NSDate (NSDate_JSON)
-(NSString *) JSONFragment{
NSString *strRepr = [self description];
return [strRepr JSONFragment];
}
-(id) initWithJSONRepresentation:(NSString *)aJSONRepresentation{
return [self initWithString: aJSONRepresentation]; //returns nil!
}
@end
我不确定发生了什么。此外,编译器警告我无法找到initWithJSONRepresentation:中的initWithString:方法。
有人知道可能会发生什么吗?
测试用例的完整源代码可用here。
答案 0 :(得分:3)
在尝试将字符串转换为日期时,总是使用NSDateFormatter
,反之亦然。 -initWithString:
确实存在于Mac上,但不存在于iOS上。它要求字符串格式非常精确。使用日期格式化程序是目前最好的解决方案。
作为旁注,如果Apple决定更改-[NSDate description]
的格式,您的代码就会中断。
答案 1 :(得分:2)
您的测试程序是:
NSDate *d1 = [[[NSDate alloc] init] autorelease];
NSString *repr = [d1 JSONFragment];
NSDate *dd = [[[NSDate alloc] initWithString:[d1 description]] autorelease ];
NSDate *d2 = [[[NSDate alloc] initWithJSONRepresentation:repr] autorelease];
您的-JSONFragment
类别方法是:
-(NSString *) JSONFragment{
NSString *strRepr = [self description];
return [strRepr JSONFragment];
}
此方法中发生的情况是您使用-description
获取该日期的字符串表示形式,然后使用-JSONFragment
获取该字符串的JSON表示。
在SBJSON中,-JSONFragment
将给定对象的表示形式返回为JSON数据。 JSON规范要求引用字符串。在你的计划中:
NSString *repr = [d1 JSONFragment];
repr
包含@"\"2011-04-29 10:20:30 -0600\""
之类的字符串。由于引号,该字符串不是与-[NSDate initWithString:]
一起使用的有效字符串。
如果你改变:
NSString *repr = [d1 JSONFragment];
为:
NSString *repr = [[d1 JSONFragment] JSONFragmentValue];
以便SBJSON解析该片段并返回不带引号的字符串,它应该可以工作。
答案 2 :(得分:1)
找不到initWithString:
的原因是除非您导入Foundation并且没有在此处显示,否则您的代码无法看到NSDate.h,因此它不知道{{1} 1}}存在。
Dave完全依赖initWithString:
并使用description
代替。 NSDateFormatter
似乎不太可能会发生变化,但无法保证它会继续作为description
initWithString:
的有效输入has a strict input requirement:
以国际字符串表示格式指定日期和时间值的字符串 -
YYYY-MM-DD HH:MM:SS ±HHMM
,其中±HHMM
是GMT小时和分钟的时区偏移量(例如,“{{1 }}”)。您必须指定格式字符串的所有字段,包括时区偏移量,该字段必须具有加号或减号前缀。
如果你的字符串以任何方式有所不同(包括显而易见的,在其中加上引号),你将获得2001-03-24 10:45:32 +0600
。