围绕 NSJSONSerialization 的小型包装,用于解析 JSON。其主要功能包括 围绕 NSJSONSerialization 的包装
- 详细错误报告。
- 错误处理基于抛出异常而不是“if 地狱”。
- 类型检查。
- 流畅的 API。
示例
@interface Menu : NSObject
@property (nonatomic) NSString *header;
@property (nonatomic) NSNumber *height;
@property (nonatomic) NSNumber *width;
@end
@implementation Menu
+ (POSJSONMap *)exampleJSON {
return [[POSJSONMap alloc] initWithData:[
@"{\"menu\": {"
" \"header\": \"SVG Viewer\","
" \"height\": 500,"
" \"items\": ["
" {\"id\": \"Open\"},"
" {\"id\": \"OpenNew\", \"label\": \"Open New\"},"
" null,"
" {\"id\": \"ZoomIn\", \"label\": \"Zoom In\"},"
" ]"
"}}"
dataUsingEncoding:NSUTF8StringEncoding]];
}
+ (Menu *)parseMenu:(NSError **)error {
@try {
POSJSONMap *JSON = [[[self exampleJSON] extract:@"menu"] asMap];
Menu *menu = [Menu new];
// mandatory parameters
menu.header = [[JSON extract:@"header"] asString];
menu.height = [[JSON extract:@"height"] asNumber];
// optional parameters
menu.width = [[JSON tryExtract:@"width"] asNumber];
return menu;
}
@catch (NSException *exception) {
if (error) {
*error = [NSError errorWithDomain:@"com.example"
code:0
userInfo:@{ NSLocalizedDescriptionKey: [exception reason] }];
}
return nil;
}
}
@end
如果在示例中将 [[JSON tryExtract:@"width"] asNumber]
替换为 [[JSON extract:@"width"] asNumber]
,那么会抛出以下原因的异常
'root.menu' doesn't contain object with key 'width' in JSON:
{
"menu": {
"header": "SVG Viewer",
"height": 500,
"items": [
{"id": "Open"},
{"id": "OpenNew", "label": "Open New"},
null,
{"id": "ZoomIn", "label": "Zoom In"},
]
}
}
备注
正如我们所知,NSException 和 ARC 并不是最好的朋友。同时,通常 JSON 是您的应用程序与某个远程服务之间的合同。如果一切都是好的,那么将不会有任何异常,在另一种情况下,存在某种合同违规,您比在格式错误的 JSON 解析期间泄漏的对象有更严重的问题。例如,NSKeyedArchiever 在解包归档期间以相同的方式通知客户端有关错误。
祝您享受!