📜 ⬆️ ⬇️

Super simple iOS JSON mapper

Anyone who has written a client-server application for iOS at least once has somehow come across json / xml / other mapping into objects. Sometimes it is difficult, sometimes you just want to work with dictionaries, there are already many ready-made solutions like RestKit, which generally is a universal combine for all occasions, so why write another bike?

The reasons may be many, several of them, which led me to write my mini-mapper, this:



First of all, the link to GitHub , where the source code of the base class for our future models lies and an example of a project using the mapper.
')
Before praising or something else, I will describe the cons:


Of the benefits - easy to use, tiny in size as well as in the number of classes that you have to figure out if something happens, it does its job.

How to work with him? Mapper consists of one class - TinyMappingModel, this is the base class for all subsequent classes of the model. For each json object, a TinyMappingModel successor is created, which must contain properties for storing the necessary data. Ideally, you should call them the same way as the corresponding fields in json are called - then mapping will occur by itself, as if by magic (KVC), about cases where this is not possible (for example, a field named im: name, id, 1work ), I will write below.

TinyMappingModel contains 4 methods:

//public + (instancetype)mapObjectFromDictionary:(NSDictionary *)data; + (NSArray *)mapArrayOfObjects:(NSArray *)data; //protected methods - (NSDictionary *)keyToClassMappingRules; - (NSDictionary *)keyToPropertyNameReplacementRules; 

Heirs by necessity must override the last two.

- (NSDictionary *) keyToClassMappingRules; - redefined in case we need to wrap the json object into some custom class (TinyMappingModel heir) or into an array. The method must return a dictionary with pairs of keys - the name of the field in json, value - the class in which the object will be mapped or, in the case of a collection, which objects the collection will consist of. For example:

 - (NSDictionary *)keyToClassMappingRules { return @{@"im:name":[TitleModel class], @"im:image":[ImageModel class]}; } 

- (NSDictionary *) keyToPropertyNameReplacementRules; - redefined in case we cannot / want for some reason to name a property in a class just as it is called in json. The key is the name of the field in json, the value is the name of the property in the class, for example:

 - (NSDictionary *)keyToPropertyNameReplacementRules { return @{@"im:name":@"name",@"im:image":@"images"}; } 

These two methods from the example will be the only thing that is minimally necessary to implement in the implementation. In our class header (for example, EntryModel) there will be:

 @class TitleModel; @interface EntryModel : TinyMappingModel @property (nonatomic, strong) TitleModel *name; @property (nonatomic, strong) NSArray *images; @end 

With name everything is clear, objects like ImageModel will be stored in the images array, and, of course, you need to import the necessary classes (in this case, ImageModel and TitleModel) in the implementation, you could, of course, do it on strings, and then NSClassFromString, but not .

Further, how to work? When we got the data from the network and somehow converted it to json (for example, I often use AFNetworking in small projects), it follows:

 //data - NSDictionary c json EntryModel *model= [EntryModel mapObjectFromDictionary:data]; // data - NSArray EntryModel *modelArray= [EntryModel mapArrayOfObjects:data]; 

Variations are possible. The main thing is to transfer the correct object to the correct method, it will understand there, nothing complicated.

In a nutshell I will describe how the mapper works.
The most important method + (instancetype) mapObjectFromDictionary: (NSDictionary *) data, it actually does all the work - creates a future model, iterates over json keys, decides what we will map (class - depending on what we have in keyToClassMappingRules and in which nominal property - depending on keyToPropertyNameReplacementRules). Further, depending on what data is for the current key and what we are going to map, there are three ways in which events can develop:


That's all. To summarize, we have three “entities” - what map, which class map or primitive, which map property (or if not specified, the property named json key), and depending on whether a value that is mapped or not is called mapObjectFromDictionary or mapArrayOfObjects, respectively. mapArrayOfObjects essentially does no work, creates an array and puts [self mapArrayOfObjects: value] or [mappedArray addObject: [self mapObjectFromDictionary: value], where value is the value obtained during the iteration over the input array. That's all.

Thank you for your attention, I wonder your opinion about usability, and, if you looked at the source, about the mapper.

Source: https://habr.com/ru/post/181740/


All Articles