The easiest way to marshall and unmarshall Dictionary representations such as JSON representation
An easy way to unmarshall a Dictionary of attributes (which came from JSON, XML or just a NSDictionary) into a Class and vice versa.
Developed by Lucas Medeiros and Denys Telezhkin
E-mail: [email protected]
Add package into Project settings -> Swift Packages
pod 'EasyMapping', '~> 0.20'
github “EasyMapping/EasyMapping”
typedef enum {
GenderMale,
GenderFemale
} Gender;
@interface Person : NSObject <EKMappingProtocol>
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *email;
@property (nonatomic, assign) Gender gender;
@property (nonatomic, strong) Car *car;
@property (nonatomic, strong) NSArray *phones;
@property (nonatomic, strong) NSURL * socialURL;
@end
@interface Car : NSObject <EKMappingProtocol>
@property (nonatomic, copy) NSString *model;
@property (nonatomic, copy) NSString *year;
@property (nonatomic, strong) NSDate *createdAt;
@end
@interface Phone : NSObject <EKMappingProtocol>
@property (nonatomic, copy) NSString *DDI;
@property (nonatomic, copy) NSString *DDD;
@property (nonatomic, copy) NSString *number;
@end
@interface Native : NSObject <EKMappingProtocol>
@property (nonatomic, readwrite) NSInteger integerProperty;
@property (nonatomic, readwrite) NSUInteger unsignedIntegerProperty;
@property (nonatomic, readwrite) CGFloat cgFloatProperty;
@property (nonatomic, readwrite) double doubleProperty;
@property (nonatomic, readwrite) BOOL boolProperty;
@end
@implementation Person
+(EKObjectMapping *)objectMapping
{
return [EKObjectMapping mappingForClass:self withBlock:^(EKObjectMapping *mapping) {
NSDictionary *genders = @{ @"male": @(GenderMale), @"female": @(GenderFemale) };
[mapping mapPropertiesFromArray:@[@"name", @"email"]];
[mapping mapKeyPath:@"gender" toProperty:@"gender" withValueBlock:^(NSString *key, id value) {
return genders[value];
} reverseBlock:^id(id value) {
return [genders allKeysForObject:value].lastObject;
}];
[mapping mapKeyPath:@"socialURL" toProperty:@"socialURL"
withValueBlock:[EKMappingBlocks urlMappingBlock]
reverseBlock:[EKMappingBlocks urlReverseMappingBlock]];
[mapping hasOne:[Car class] forKeyPath:@"car"];
[mapping hasMany:[Phone class] forKeyPath:@"phones"];
}];
}
@end
@implementation Car
+(EKObjectMapping *)objectMapping
{
return [EKObjectMapping mappingForClass:self withBlock:^(EKObjectMapping *mapping) {
[mapping mapPropertiesFromArray:@[@"model", @"year"]];
[mapping mapKeyPath:@"created_at" toProperty:@"createdAt" withDateFormatter:[NSDateFormatter ek_formatterForCurrentThread]];
}];
}
@end
@implementation Phone
+(EKObjectMapping *)objectMapping
{
return [EKObjectMapping mappingForClass:self withBlock:^(EKObjectMapping *mapping) {
[mapping mapPropertiesFromArray:@[@"number"]];
[mapping mapPropertiesFromDictionary:@{
@"ddi" : @"DDI",
@"ddd" : @"DDD"
}];
}];
}
@end
@implementation Native
+(EKObjectMapping *)objectMapping
{
return [EKObjectMapping mappingForClass:self withBlock:^(EKObjectMapping *mapping) {
[mapping mapPropertiesFromArray:@[
@"integerProperty", @"unsignedIntegerProperty",
@"cgFloatProperty", @"doubleProperty",
@"boolProperty"
]];
}];
}
@end
Person *person = [EKMapper objectFromExternalRepresentation:personRepresentation
withMapping:[Person objectMapping]];
NSArray *carsArray = [EKMapper arrayOfObjectsFromExternalRepresentation:carsRepresentation
withMapping:[Car objectMapping]];
NSDictionary *representation = [EKSerializer serializeObject:car withMapping:[Car objectMapping]];
NSArray *collectionRepresentation = [EKSerializer serializeCollection:cars withMapping:[Car objectMapping]];
Suppose you have something like this:
Person *person = [Person alloc] init]
To fill an already instantiated object you can do this:
[EKMapper fillObject:person fromExternalRepresentation:personRepresentation withMapping:[Person objectMapping]];
EasyMapping is partially compatible with Swift. Here’s detailed look at EasyMapping usage in Swift and current limitations.
EasyMapping provides two convenience base classes: EKObjectModel and EKManagedObjectModel, that implement EKMappingProtocol by default. If, for example, class Person would inherit from EKObjectModel, and implemented objectMapping method, all it would take to create Person instance from JSON representation would be:
NSDictionary * parsedPersonInfo = ...;
Person * person = [Person objectWithProperties:parsedPersonInfo];
And CoreData variant in case Person is EKManagedObjectModel subclass:
NSDictionary * parsedPersonInfo = ...;
Person * person = [Person objectWithProperties:parsedPersonInfo inContext:context];
Serializing to NSDictionary is even easier:
NSDictionary * info = [person serializedObject];
If you are using CoreData objects use EKManagedObjectMapping
instead of EKObjectMapping
. EasyMapping tries to speed up importing to database by scanning provided JSON and fetching all existing objects in batch. The more high level JSON will be provided, the more speed boost can be achieved.
Sometimes you can encounter situation, where your JSON will contain objects with links to objects of the same type. Good example would be comments, and replies to comments, that have tree-like structure. Starting with 0.7.0 recursive mappings are fully supported by EasyMapping.
Thanks to:
The idea came from: