html текст
All interests
  • All interests
  • Design
  • Food
  • Gadgets
  • Humor
  • News
  • Photo
  • Travel
  • Video
Click to see the next recommended page
Like it
Don't like
Add to Favorites

EasyMapping, или Путешествие по JSON'у из песочницы

Computer programs are the most complex things that humans make. It is also the nature of software to be extensively modified over its productive life. If we can read and understand it, then we can hope to modify and improve it.

© Douglas Crockford, автор спецификации JSON


JSON — это мост между двумя мирами: миром веб-сервисов и миром клиентских приложений. Однако мост не настолько совершенен, чтобы данные существовали в одном формате. Пока что мы всегда вынуждены преобразовывать информацию в представление того языка, с которым работаем, для архитектуры того приложения, которое пишем. Для того чтобы такое преобразование было успешным, оно должно быть в первую очередь простым.

Есть много способов превращения JSON в Objective-C обьекты, однако многие из них имеют свои недостатки, которые мешают с ними работать. Есть известный и любимый многими RestKit, однако он, к сожалению, эффективно работает только при наличии идеального REST API. Шаг в сторону — и вы будете забивать гвозди микроскопом, не понимая, зачем нужно писать такие сложные конструкции для достаточно простых вещей. Есть решение от разработчиков GitHub — Mantle, однако с ним вы будете вынуждены наследоваться от базового класса Mantle и постоянно использовать NSValueTransformer — не самую популярную технологию в iOS/Mac OS разработке.

Я хочу рассказать о фреймворке, который недавно нашелся на просторах GitHub, и который позволяет достаточно просто и красиво преобразовывать JSON в Objective-C обьекты — EasyMapping.

Если заинтересовались, добро пожаловать под кат!

Задача


Возьмем для примера следующий JSON:

{
    "name": "Lucas",
    "email": "notexisting@gmail.com",
    "gender" : "male",
    "car": {
        "model": "i30",
        "year": "2013"
    },
    "phones": [
        {
            "ddi": "55",
            "ddd": "85",
            "number": "1111-1111"
        },
        {
            "ddi": "55",
            "ddd": "11",
            "number": "2222-222"
        }
    ]
}


В Objective-C будем использовать такие классы:

typedef enum {
    GenderMale,
    GenderFemale
} Gender;

@interface Person : NSObject

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

@end

@interface Car : NSObject

@property (nonatomic, copy) NSString *model;
@property (nonatomic, copy) NSString *year;

@end

@interface Phone : NSObject

@property (nonatomic, copy) NSString *DDI;
@property (nonatomic, copy) NSString *DDD;
@property (nonatomic, copy) NSString *number;

@end


Реализация


Для каждого класса необходимо создать маппинг (EKObjectMapping), например:

EKObjectMapping * mapping = [[EKObjectMapping alloc] initWithObjectClass:[Person class]];


После чего необходимо добавить соотношения ключ-значение для связи <ключ в JSON> -> <имя свойства обьекта>. Рассмотрим наиболее часто встречающиеся ситуации при маппинге и обработку этих ситуаций при помощи EasyMapping.

1. Ключи в JSON совпадают с именами свойств обьекта

Пример, класс Person:

[mapping mapFieldsFromArray:@[@"name",@"email"]];


2. Ключи в JSON отличаются от имен свойств обьекта

Пример, класс Phone:

[mapping mapFieldsFromDictionary:@{@"ddi":@"DDI", @"ddd":@"DDD"}];


3. Значение требует дополнительной обработки

Пример, класс Person

NSDictionary *genders = @{ @"male": @(GenderMale), @"female": @(GenderFemale) };
[mapping mapKey:@"gender" toField:@"gender" withValueBlock:^(NSString *key, id value) {
    return genders[value];
}]; 


4. Обьект содержит обьект другого класса

Пример, класс Person

[mapping hasOneMapping:[Car objectMapping] forKey:@"car"];


5. Обьект содержит массив обьектов другого класса

Пример. Класс Person

[mapping hasManyMapping:[Phone objectMapping] forKey:@"phones"];


Результат


Полностью маппинги для наших классов:


// Car mapping
+ (EKObjectMapping *)objectMapping
{
	EKObjectMapping * mapping = [[EKObjectMapping alloc] initWithObjectClass:[Car class]];

    [mapping mapFieldsFromArray:@[@"model", @"year"]];

    return mapping;
}

// Phone mapping
+ (EKObjectMapping *)objectMapping
{
	EKObjectMapping * mapping = [[EKObjectMapping alloc] initWithObjectClass:[Phone class]];
    [mapping mapFieldsFromArray:@[@"number"]];
    [mapping mapFieldsFromDictionary:@{
        @"ddi" : @"DDI",
        @"ddd" : @"DDD"
     }];
    return mapping;
}

// Person mapping
+ (EKObjectMapping *)objectMapping
{
	EKObjectMapping * mapping = [[EKObjectMapping alloc] initWithObjectClass:[Person class]];

    NSDictionary *genders = @{ @"male": @(GenderMale), @"female": @(GenderFemale) };
    [mapping mapFieldsFromArray:@[@"name", @"email"]];
    [mapping mapKey:@"gender" toField:@"gender" withValueBlock:^(NSString *key, id value) {
        return genders[value];
    }];
    [mapping hasOneMapping:[Car objectMapping] forKey:@"car"];
    [mapping hasManyMapping:[Phone objectMapping] forKey:@"phones"];

    return mapping;
}


Теперь, когда маппинг готов, создание обьекта Person выглядит следующим образом:

NSDictionary * personProperties = ...; // JSON обьекта Person, приведенный выше, распарсенный в словарь.
Person * person = [[Person alloc] init];
[EKMapper fillObject:person fromExternalRepresentation:personProperties withMapping:mapping];


Таким образом, при создании обьекта не используются никакие конструкции if-else, отсутствуют проверки на NSNull. Кроме того, существующие обьекты можно легко обновить новыми данными, если такая потребность возникнет.

Дополнительные плюшки EasyMapping

1. Поддержка CoreData
2. Встроенная проверка на NSNull — NSNull автоматически заменяется на nil.
3. Возможность сериализации обьектов в NSDictionary/NSArray
4. Поддержка установки через CocoaPods
5. Полностью покрыт тестами.

Удачные практики при реализации

Заполнение обьекта при помощи EKMapper лучше вынести в базовый класс, скажем, BaseModel, следующим образом:

- (id)initWithProperties:(NSDictionary *)properties
{
    if (self = [super init])
    {
        [EKMapper fillObject:self fromExternalRepresentation:properties
                 withMapping:[[self class] objectMapping];
    }
    return self;
}

+ (EKObjectMapping *)objectMapping
{
    //Do nothing. Implement in subclass if you want to initialize object
    //via object mapping
    return nil;
}


Таким образом, создание обьекта будет выглядеть так:

Person * person = [[Person alloc] initWithProperties:personProperties];


Заключение


Каждый качественный open-source продукт — это трамплин, который позволяет нам как программистам прыгать все выше и выше. Проекту EasyMapping всего лишь один месяц, если судить по первому коммиту, однако, на мой взгляд, он уже может соперничать с намного более старыми и продвинутыми решениями, по крайней мере, своей простотой. Хочется пожелать удачи автору этого интересного фреймворка, а всем, кто дочитал до конца, — спасибо за ваше время и удачи в путешествиях по JSON'у!

Ссылки


1. EasyMapping на github
2. CocoaPods

Альтернативные решения

1. RestKit
2. Mantle
Читать дальше
Twitter
Одноклассники
Мой Мир

материал с habrahabr.ru

1

      Add

      You can create thematic collections and keep, for instance, all recipes in one place so you will never lose them.

      No images found
      Previous Next 0 / 0
      500
      • Advertisement
      • Animals
      • Architecture
      • Art
      • Auto
      • Aviation
      • Books
      • Cartoons
      • Celebrities
      • Children
      • Culture
      • Design
      • Economics
      • Education
      • Entertainment
      • Fashion
      • Fitness
      • Food
      • Gadgets
      • Games
      • Health
      • History
      • Hobby
      • Humor
      • Interior
      • Moto
      • Movies
      • Music
      • Nature
      • News
      • Photo
      • Pictures
      • Politics
      • Psychology
      • Science
      • Society
      • Sport
      • Technology
      • Travel
      • Video
      • Weapons
      • Web
      • Work
        Submit
        Valid formats are JPG, PNG, GIF.
        Not more than 5 Мb, please.
        30
        surfingbird.ru/site/
        RSS format guidelines
        500
        • Advertisement
        • Animals
        • Architecture
        • Art
        • Auto
        • Aviation
        • Books
        • Cartoons
        • Celebrities
        • Children
        • Culture
        • Design
        • Economics
        • Education
        • Entertainment
        • Fashion
        • Fitness
        • Food
        • Gadgets
        • Games
        • Health
        • History
        • Hobby
        • Humor
        • Interior
        • Moto
        • Movies
        • Music
        • Nature
        • News
        • Photo
        • Pictures
        • Politics
        • Psychology
        • Science
        • Society
        • Sport
        • Technology
        • Travel
        • Video
        • Weapons
        • Web
        • Work

          Submit

          Thank you! Wait for moderation.

          Тебе это не нравится?

          You can block the domain, tag, user or channel, and we'll stop recommend it to you. You can always unblock them in your settings.

          • habrahabr.ru
          • домен habrahabr.ru

          Get a link

          Спасибо, твоя жалоба принята.

          Log on to Surfingbird

          Recover
          Sign up

          or

          Welcome to Surfingbird.com!

          You'll find thousands of interesting pages, photos, and videos inside.
          Join!

          • Personal
            recommendations

          • Stash
            interesting and useful stuff

          • Anywhere,
            anytime

          Do we already know you? Login or restore the password.

          Close

          Add to collection

             

            Facebook

            Ваш профиль на рассмотрении, обновите страницу через несколько секунд

            Facebook

            К сожалению, вы не попадаете под условия акции