我认为这JSONEncoder
主要是为了对来自自定义类的对象(必须实现NSCoding
协议)进行编码。例如,如果您定义一个Person
具有字符串属性的类:
@interface Person : NSObject <NSCoding>
@property(strong, nonatomic) NSString *name;
@end
@implementation Person
- (id)initWithCoder:(NSCoder *)coder {
if ((self = [super init])) {
self.name = [coder decodeObjectForKey:@"name"];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)coder {
[coder encodeObject:self.name forKey:@"name"];
}
@end
那么您可以使用以下方法对此类的对象进行编码而不会出现问题JSONEncoder
:
JSONEncoder *encoder = [JSONEncoder encoder];
Person *obj = [[Person alloc] init];
obj.name = @"John";
[encoder encodeObject:obj];
NSString *json = [encoder json];
NSLog(@"%@", json);
// Output: {"person":{"name":"John"}}
它也适用于一些“普通”的 Foundation 类型,例如 with NSNumber
,但输出不是很“好”,我不确定是否JSONEncoder
打算这样使用:
JSONEncoder *encoder = [JSONEncoder encoder];
NSNumber *obj = @1234;
[encoder encodeObject:obj];
NSString *json = [encoder json];
NSLog(@"%@", json);
// Output: {"__NSCFNumber":{"NS.intval":1234}}
在这种情况下,encodeInt64:forKey:
方法JSONEncoder
是在内部调用。
但是,正如您所注意到的,它不适用于NSString
:
JSONEncoder *encoder = [JSONEncoder encoder];
NSString *obj = @"Hello world";
[encoder encodeObject:obj];
// Exception: *** -encodeBytes:length:forKey: only defined for abstract class. Define -[JSONEncoder encodeBytes:length:forKey:]!
异常的原因NSString
是NSCoding
合规的,但是它使用-encodeBytes:length:forKey:
了编码器的,并且JSONEncoder
没有实现这个方法。
实现该方法并不太困难,这是一个快速而肮脏的尝试:
- (void)encodeBytes:(const uint8_t *)bytesp length:(NSUInteger)lenv forKey:(NSString *)key
{
NSString *s = [[NSString alloc] initWithBytes:bytesp length:lenv encoding:NSUTF8StringEncoding];
[self setObject:s forKey:key];
}
如果将此代码添加到“JSONEncoder.m”,那么您可以编码纯文本NSString
而不会出现异常,结果如下所示:
{"__NSCFConstantString":{"NS.bytes":"Hello world"}}
但同样,我不确定是否JSONEncoder
要这样使用。