Developed and Maintained by ipodishima Founder & CTO at Wasappli Inc.
Sponsored by Wisembly
A fast mapper from JSON to NSObject
- Fast
- Simple to write & read
- Saves you many hours
- Supports both JSON <->
NSObject
- Designed for customisation
- Built-in CoreData, NSCoding and Memory stores
- Built-in insert or update object
- Tested
Go visit the wiki for more details about WAMapping
advanced use.
WAMapping is a library for iOS to turns dictionaries into objects and objects to dictionary. It's aim is to simplify the boilerplate of manually parsing the data and assigning values to an object. It's even more difficult when it comes to using it with CoreData because of the insert or update. And I do not mention performances involved. WAMapping solves this for you!
Use Cocoapods, this is the easiest way to install the mapper.
pod 'WAMapping'
#import <WAMapping/WAMapping.h>
On a classical use, the source
is known as the response from a server turned into a dictionary and the destination
is the destination object to apply the values, for example an NSManagedObject
.
Let's assume the Enterprise
class as follows:
@interface Enterprise : NSObject
@property (nonatomic, strong) NSNumber *itemID;
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSDate *creationDate;
@property (nonatomic, strong) NSNumber *streetNumber;
@property (nonatomic, strong) NSArray *employees; // Can be mutable, or an `NSSet` or an `NSOrderedSet`
@property (nonatomic, strong) NSArray *chiefs;
@end
The itemID
ids your object on the store. This is not required but recommended to avoid creating duplicates.
Assuming a json
{
"id": 1,
"name": "Wasappli",
"creation_date": "2013-10-01",
"address": {
"street_number": 5149
}
}
The mapping would looks like
WAEntityMapping *enterpriseMapping = [WAEntityMapping mappingForEntityName:@"Enterprise"];
enterpriseMapping.identificationAttribute = @"itemID";
// Add the classic attributes
[enterpriseMapping addAttributeMappingsFromDictionary:@{
@"id": @"itemID",
@"name": @"name",
@"address.street_number": @"streetNumber"
}];
// Map custom values. Here an `NSDate` from a string using an `NSDateTransformer`
[enterpriseMapping addMappingFromSourceProperty:@"creation_date"
toDestinationProperty:@"creationDate"
withBlock:^id(id value) {
return [dateFormatter dateFromString:value];
}
reverseBlock:^id(id value) {
return [dateFormatter stringFromDate:value];
}];
// Register the mapping for future use
WAMappingRegistrar *registrar = [WAMAppingRegistrar new];
[registrar registerMapping:enterpriseMapping];
// [registrar registerMapping:employeeMapping];
// WAEntityMapping *savedEnterpriseMapping = [registrar mappingForEntityName:@"Enterprise"];
And that's it...!
First, create a store. This is a required step. I'm providing three stores on this repo:
WAMemoryStore
which relies on a simpleNSMutableSet
,WANSCodingStore
which saves your objects usingNSCoding
protocol,WACoreDataStore
which makes use ofCoreData
.
You can easily create your own store is you want to use SQLite for example, go checkout the wiki.
WAMemoryStore *store = [[WAMemoryStore alloc] init];
// or
// WACoreDataStore *store = [[WACoreDataStore alloc] initWithManagedObjectContext:localContext];
// or
// WANSCodingStore *store = [[WANSCodingStore alloc] initWithArchivePath:archivePath];
Then, allocate a mapper with the store
WAMapper *mapper = [[WAMapper alloc] initWithStore:store];
Finally, map the dictionary representation to the object:
[mapper mapFromRepresentation:json
mapping:enterpriseMapping
completion:^(NSArray *mappedObjects) {
firstEnterprise = [mappedObjects firstObject];
}];
And voilà!
WAMapping
also supports relationships:
- classics:
{
"id": 1,
"first_name": "Marian",
"enterprise": {
"id": 1,
"name": "Wasappli",
"creation_date": "2013-10-01",
"address": {
"street_number": 5149
}
}
}
WARelationshipMapping *enterpriseRelationship =
[WARelationshipMapping relationshipMappingFromSourceProperty:@"enterprise" toDestinationProperty:@"enterprise" withMapping:enterpriseMapping];
[employeeMapping addRelationshipMapping:enterpriseRelationship];
- With identification attribute only
{
"enterprise": {
"id": 1,
"name": "Wasappli",
"creation_date": "2013-10-01",
"address": {
"street_number": 5149
},
"chiefs": 1 # Could also be [1, 2, 3]
},
"employees": [{
"id": 1,
"first_name": "Marian"
}]
}
WARelationshipMapping *chiefsRelationship = [WARelationshipMapping relationshipMappingFromSourceIdentificationAttribute:@"chiefs" toDestinationProperty:@"chiefs" withMapping:employeeMapping];
[enterpriseMapping addRelationshipMapping:chiefsRelationship];
A reverse mapper is also packaged with this library. It supports the reverse transformation from an object to a dictionary.
WAReverseMapper *reverseMapper = [[WAReverseMapper alloc] init];
json = [reverseMapper reverseMapObjects:enterprises
fromMapping:enterpriseMapping
shouldMapRelationship:nil];
- Benchmark against popular mappers
- Add more tests for keypath handling, especially on relationship
You'll find inspiration from Restkit and FastEasyMapping. These are both libraries I used on projects but with issues
#Contributing : Problems, Suggestions, Pull Requests?
Please open a new Issue here if you run into a problem specific to WAAppRouting.
For new features pull requests are encouraged and greatly appreciated! Please try to maintain consistency with the existing code style. If you're considering taking on significant changes or additions to the project, please ask me before by opening a new Issue to have a chance for a merge.
#That's all folks !
- If your are happy don't hesitate to send me a tweet @ipodishima!
- Distributed under MIT licence.
- Follow Wasappli on facebook