TestsTested | ✗ |
LangLanguage | Obj-CObjective C |
License | MIT |
ReleasedLast Release | Dec 2014 |
Maintained by Unclaimed.
LLModel is a library for mapping the JSON data to object properties. It works perfectly well alongside with AFNetwoking.
LLModel:
Say you have the following three models:
And the JSON data we will be receiving is going to be User which contains one Address and many Feeds.
Here I will show only the User model (download the example to see other models). First of all, you have to subclass 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
In the implementation file, you need to override the initWithJSON:(id)JSON method and define your mapping. Mapping is very basic,
There is no need to worry about the types, LLModel will check the property types at runtime and assign the values accordingly.
@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
And finally, after you make a call to an API, initialize the LLModel instance (User) with the received JSON. That's it!
// 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];
In the above example the most interesting part is the mapping of the "address" and "feeds" properties.
LLModel simply gets the values from the JSON and creates an Address object (Address model should also be a subclass of LLModel) and assigns to property.
Feeds are a little bit different story. Since feeds property is defined as NSMutableArray (or it can be NSArray) LLModel can't know which type of objects it must contain.
Therefore, in the mapping, you have to provide a dictionary with the keys: key and type. LLModel will then create the Feed objects and add them to NSarray and finally will assign to the property.
If you want to receive the object values in the form of JSON data, you can simply call the (NSDictionary *)reverseMapping method. Well, if you wonder, reverse mapping is also recursive. In other words, if you call this on a User instance, you will also get Address and Feeds JSON inside the main JSON object.
LLModel will add NSerror objects to self.mappingErrors if there are any errors while parsing the JSON. You can log the errors with the helper method [self logAllMappingErrors].
If you want to initalize array of JSON values in just one function call, instead of a for loop, here is the solution:
NSArray *cities = [City batch:[JSON valueForKey:@"data"]];
LLModel has a default implementation for (NSString *)description. This method prints all the properties with their values, so you can easily debug your application.
I recommend creating a BaseModel which will be a subclass of LLModel. All of your models then should subclass BaseModel instead of LLModel directly. One of the main reasons for this approach is because many of the dates you receive from JSON will have the same date format, so in BaseModel you can define the date formatter only once.
Please download the example project to see how the entire system works.
Ömer Faruk Gül