LLModel 是一个将 JSON 数据映射到对象属性的库。它与 AFNetworking 工作得非常好。
LLModel
假设您有以下三个模型:
我们将接收的 JSON 数据将是用户,其中包含一个地址和多个馈送。
在这里,我只将展示 User 模型(下载示例查看其他模型)。首先,您必须从 LLModel 派生一个子类。
@interface User : LLModel
@property (strong, nonatomic) NSNumber *userId;
@property (strong, nonatomic) NSString *firstName;
@property (strong, nonatomic) NSString *lastName;
@property (strong, nonatomic) NSString *username;
@property (nonatomic) BOOL publicProfile;
@property (nonatomic) NSInteger loginCount;
@property (strong, nonatomic) NSDate *createdAt;
@property (strong, nonatomic) Address *address;
@property (strong, nonatomic) NSMutableArray *feeds;
@end
在实现文件中,您需要重写 initWithJSON:(id)JSON 方法并定义您的映射。映射非常简单,
无需担心类型,LLModel 会在运行时检查属性类型并相应地分配值。
@implementation User
- (id)initWithJSON:(id)JSON
{
self = [super initWithJSON:JSON];
if(self) {
self.mappingDateFormatter = [[NSDateFormatter alloc] init];
[self.mappingDateFormatter setDateFormat:@"dd.MM.yyyy"];
NSDictionary *mapping = @{@"userId":@"id",
@"firstName":@"first_name",
@"lastName":@"last_name",
@"username":@"username",
@"publicProfile":@"public_profile",
@"loginCount":@"login_count",
@"createdAt":@"created_at"
@"address":@"address",
@"feeds":@{@"key":@"feeds",@"type":@"Feed"}};
[self setValuesWithMapping:mapping andJSON:JSON];
// check if there are any errors
if(self.mappingErrors.count > 0) {
[self logAllMappingErrors];
}
}
return self;
}
@end
最后,在调用 API 后,使用接收到的 JSON 初始化 LLModel 实例(User)。就这么简单!
// The JSON from the folowing URL is generated specially for this project.
NSURL *url = [NSURL URLWithString:@"http://www.dailypul.se/api/v1/test/llmodel"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
// Simply init the user with JSON, that's all!
self.user = [[User alloc] initWithJSON:JSON];
Feed *feed = [self.user.feeds objectAtIndex:0];
// Log the model values
NSLog(@"User description: %@", self.user.description);
NSLog(@"User Address description: %@", self.user.address.description);
NSLog(@"User Feed[0] description: %@", feed.description);
NSLog(@"User dictionary: %@", [self.user reverseMapping]);
NSLog(@"Feed dictionary: %@", [feed reverseMapping]);
} failure:nil];
[operation start];
在上面的示例中,最有趣的部分是 "address" 和 "feeds" 属性的映射。
LLModel 简单地从 JSON 中获取值并创建一个 Address 对象(Address 模型也应该是 LLModel 的子类)并将其分配给属性。
馈送稍有不同的故事。由于 *feeds* 属性定义为 NSMutableArray(或它可以是一个 NSArray),LLModel 无法知道它必须包含哪种类型的对象。
因此,在映射中,您必须提供一个包含键的字典:*key* 和 *type*。然后 LLModel 将创建 Feed 对象并添加到 NSarray 中,最后将其分配给属性。
如果您想以JSON数据的格式接收对象值,您只需调用(NSDictionary *)reverseMapping方法即可。哦,如果您想知道,反向映射也是递归的。换句话说,如果您在User实例上调用这个方法,您将在主JSON对象内获得Address和Feeds JSON。
LLModel在解析JSON时如果存在错误,将在self.mappingErrors中添加NSerror对象。您可以使用辅助方法[self logAllMappingErrors]记录错误。
如果您想在单个函数调用中初始化JSON值的数组,而不是使用循环,这里有一个解决方案
NSArray *cities = [City batch:[JSON valueForKey:@"data"]];
LLModel为(NSString *)description提供了一个默认实现。这个方法会打印所有属性及其值,这样您可以轻松地调试您的应用程序。
我建议创建一个BaseModel,它是LLModel的子类。您的所有模型都应该继承自BaseModel而不是直接继承自LLModel。采用这种方法的主要原因是您从JSON接收的许多日期将具有相同的日期格式,因此您可以在BaseModel中只定义一次日期格式化。
请下载示例项目以查看整个系统是如何工作的。
Ömer Faruk Gül