• Stars
    star
    403
  • Rank 103,679 (Top 3 %)
  • Language
    Objective-C
  • License
    MIT License
  • Created about 11 years ago
  • Updated 3 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

The easiest way to marshall and unmarshall Dictionary representations such as JSON representation

CI codecov.io CocoaPod platform   CocoaPod version   Swift Package Manager compatible License MIT

EasyMapping

An easy way to unmarshall a Dictionary of attributes (which came from JSON, XML or just a NSDictionary) into a Class and vice versa.

Contact:

Developed by Lucas Medeiros and Denys Telezhkin

E-mail: [email protected]

Requirements

  • Xcode 11 and higher
  • iOS 9 / tvOS 9 and higher
  • Mac OS X 10.10 and higher
  • watchOS 2.0 and higher
  • ARC

Installation

Swift Package Manager(requires Xcode 11)

Add package into Project settings -> Swift Packages

CocoaPods:

pod 'EasyMapping', '~> 0.20'

Carthage:

github "EasyMapping/EasyMapping"

Usage

  • Suppose you have these classes:
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
  • Mapping becomes as simple as implementing single method
@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
  • Converting a NSDictionary or NSArray to a object class or collection now becomes easy:
Person *person = [EKMapper objectFromExternalRepresentation:personRepresentation
                                                withMapping:[Person objectMapping]];

NSArray *carsArray = [EKMapper arrayOfObjectsFromExternalRepresentation:carsRepresentation
                                                            withMapping:[Car objectMapping]];
  • Converting an object/collection to NSDictionary/NSArray:
NSDictionary *representation = [EKSerializer serializeObject:car withMapping:[Car objectMapping]];
NSArray *collectionRepresentation = [EKSerializer serializeCollection:cars withMapping:[Car objectMapping]];
  • Filling an existent object:

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]];

Swift

EasyMapping is partially compatible with Swift. Here's detailed look at EasyMapping usage in Swift and current limitations.

Convenience classes

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];

CoreData

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.

Recursive mappings

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

Thanks to:

  • basitali who added the fillObject functionality on EKMapper!
  • Alejandro who added CoreData support!
  • Philip Vasilchenko who added the ability to serialization/deserialization of scalar types!
  • Dany L'Hébreux who added the NSSet support!
  • Jack who added mapFieldsFromMappingObject and mapFieldsFromArrayToPascalCase functionality
  • Yuri Kotov and Dmitriy which added a lot of performance improvements
  • Moya organization for awesome automated release process.

The idea

The idea came from:

  • RestKit's mapping, its problem is that it doesn't transform custom values (such as a string value to an enum)
  • Mantle's mapping, but you don't need to inherit from any class

More Repositories

1

CMFactory

Fixture loader and FactoryGirl clone for iOS
Objective-C
43
star
2

CMEnvironment

Environment variables to ios
Objective-C
26
star
3

vraptor-magicker

A vraptor-plugin to work better with jmagick a java wrapper of ImageMagick
Java
10
star
4

vraptor-cep

Plugin de vraptor para buscar endereço por cep
Java
9
star
5

sound_place

A Phoenix application to organize songs and videos retrieved from Spotify and Youtube
Elixir
7
star
6

vraptor-test

Plugin para testes de integração sobre o tomcat
Java
3
star
7

mongoid-followit

Ruby
2
star
8

react-scripts

JavaScript
2
star
9

SomeStuffDontPanic

Example from Don't Panic Presentation
Objective-C
2
star
10

ClientServerErlangExample

Simple Cliente - Server example in Erlang
Erlang
2
star
11

rslack

A Ruby master slack bot
Ruby
2
star
12

vraptor-restfulie-client

Plugin de client do restfulie para vraptor
Java
2
star
13

vraptor-twitter

Plugin de integração com twitter para vraptor
Java
2
star
14

zyper

A rails app that consumes some Zype API services
Ruby
2
star
15

mastermind-server

Mastermind game server
Ruby
1
star
16

pusher-me

A rails app that handles members without using a presence channel
Ruby
1
star
17

vscode-configs

VSCode config per language
1
star
18

cart-system

Cart system example
Ruby
1
star
19

rweather

Open Weather API usage
JavaScript
1
star
20

forum-app

A simple forum app application
Shell
1
star
21

ex_napster

An Elixir wrapper for the Napster Web API
Elixir
1
star
22

forum-api

Forum App API
Ruby
1
star
23

elixir-presentation-examples

Elixir
1
star
24

vagrant_chef_ruby_postgres

A Vagrant project with Ruby and PostgreSQL
Ruby
1
star
25

nexus

TCP Sockets communication lib
Ruby
1
star
26

forum-webapp

Forum APP Web
CSS
1
star
27

auth-challenge

Ruby
1
star
28

weatherise

Elixir
1
star
29

zype-sdk

A wrapper to the Zype Web API
Ruby
1
star