JSON model transformation libraries are often used in iOS development, and this article will review a few common open source libraries. The evaluation mainly focuses on performance, function and fault tolerance.

Objects to be evaluated:

Manually doing JSON/Model conversion can be efficient and free without using any open source libraries, but hand-written code is cumbersome and error-prone.

YYModel I built a new wheel, relatively lightweight (including.h only 5 files), support automatic JSON/Model conversion, support to define the mapping process. The API is simple and the function is relatively simple.

FastEasyMapping Yalantis is a JSON Model transformation library developed by FastEasyMapping Yalantis to customize detailed Model mapping processes and support CoreData. Fewer users.

JSONModel is a JSON model transformation library, with a relatively concise interface. The Model needs to inherit from the JSONModel.

Mantle Github official team developed JSON Model transformation library, Model needs to inherit from MTLModel. Rich function, perfect documentation, widely used.

The JSON model library developed by the domestic developer “Xiao Code brother” of MJExtension is claimed to have better performance than JSONModel and Mantle, and is simple to use and non-invasive. There are a lot of users in China.

Performance measurement:

All open source library codes were updated to 2015-09-18, compiled in Release mode, and run on iPhone 6. See github.com/ibireme/YYM for the code… .

Case 1: GithubUser from https://api.github.com/users/facebook for a User data, remove NSDate properties. The JSON has 30 rows, most of them string and a few number. This use case focuses on testing the most basic Model-related operations. Each test is performed 10000 times, and the statistics takes milliseconds.

Use case 2: WeiboStatus

Extract a complete microblog data from the official Microblog App. There are 580 lines of JSON in total (yes, a microblog needs such a large amount of data), including a large number of nested objects, container objects, type conversion, date resolution, etc. This use case mainly tests the performance of different libraries in complex situations. Each test is performed 1000 times, and the statistics are collected in milliseconds.

The test results are as follows:

Mantle has the worst performance in all tests. JSONModel and MJExtension have similar performance, but both have higher performance than Mantle. FastEasyMapping is fast indeed. YYModel performs an order of magnitude better than other libraries, approaching the efficiency of handwritten code.

FastEasyMapping does not support the NSCoding protocol, so you cannot perform Archive performance testing. There was an error in MJExtension handling the conversion of complex objects to JSON.

(HERE I have also tested some Swift projects, such as ObjectMapper, JSONHelper and ModelRocket. The performance is much worse than that of Mantle, so the comparison will not be made here.)

 

Fault tolerance:

Fault tolerance tests whether, by default, the Model framework can produce error results or Crash when the JSON format is wrong.

Use cases YYModel FastEasyMapping JSONModel Mantle MJExtension
The JSON property is number

The Model property is NSString
✅ nsstrings ? NSNumber ✅ nsstrings ⚠ ️ model nil ✅ nsstrings
The JSON property is string “100”

The Model property is int
✅ 100 ? Crash ? Crash ⚠ ️ model nil ✅ 100
The JSON attribute is string “2009-04-02T03:35:22z”.

The Model property is NSDate
✅ NSDate ? NSString ✅ NSDate ⚠ ️ model nil ? NSString
The JSON property is string

The Model property is NSValue
✅ nil ? NSString ? crash ⚠ ️ model nil ? NSString

Both YYModel and Mantle conduct object type check to avoid assigning wrong object types to attributes, so as to avoid potential Crash problems. The difference is that YYModel will try to convert automatically and leave blank when conversion fails; However, when Mantle encounters type mismatch, he directly returns the error upward, thus terminating the whole conversion process, but it is more convenient for debugging.

MJExtension will automatically convert some objects (such as between NSString and NSNumber), but when the automatic conversion cannot be completed, it will directly assign JSON objects to Model properties whose types do not match. Such a result will lead to the potential Crash risk when the Model is used later.

JSONModel does not detect error types and does not protect the App. When exceptions occur, the whole App will Crash, which is very dangerous.

FastEasyMapping performs the worst. It has no automatic conversion mechanism and can cause wrong type assignment or even direct Crash when type mismatch is encountered.

 

Function:

function YYModel FastEasyMapping JSONModel Mantle MJExtension
Automatic mapping of the same attribute name ?
Custom attribute conversion mode ? ? ?
NSCoding ?
hash/equal ? ?
CoreData ? ?

In terms of functions, Mantle has the highest customizability and relatively rich functions. YYModel, JSONModel and MJExtension are relatively simple to use, but their functions are slightly weaker than those of Mantle. FastEasyMapping is minimal and not easy to use.

Invasive:

Mantle and JSONModel both require the Model to inherit from a base class, which is less flexible but more functional.

YYModel and MJExtension both adopt Category mode to realize functions, which are flexible and non-invasive. Note, however, that MJExtension adds some unprefixed methods to NSObject/NSString, and that the method names are generic and may conflict with other classes in a project.

FastEasyMapping uses utility classes to implement Model transformations in the most flexible and cumbersome way.

Conclusion:

If a stable and powerful Model framework is needed, Mantle is the best choice, its only disadvantage is poor performance. If the function requirement is not much, but the performance requirement is higher, can try my YYModel.

Swift related libraries have poor performance and are not recommended for non-SWIFT projects.

As a final note, if you have higher requirements for performance, network traffic, etc., do not use JSON and recommend using solutions such as Protobuf /FlatBuffers instead. JSON conversions, however optimized, are far worse than binary formats in terms of performance and traffic.

Attached: Several tips for YYModel performance optimization:

1. Cache metadata of many classes during Model JSON conversion. If the data is small enough, all of them will be cached in memory.

2. Table lookup When you encounter multiple choice conditions, try to use table lookup method to achieve, such as switch/case, C Array, if the table lookup condition is an object, you can use NSDictionary to achieve.

3. Avoiding KVC key-value Coding is very convenient to use, but the performance is worse than calling Getter/Setter directly. Therefore, if you can avoid KVC and use Getter/Setter instead, the performance will be greatly improved.

4. Avoid Getter/Setter calls. If you can access IVAR directly, use IVAR instead of Getter/Setter to save some overhead.

5. Avoid redundant memory management methods Under ARC conditions, the default declared object is __strong, assignment may result in a retain/release call, if a variable is not released during its lifetime, __unsafe_unretained can save a lot of overhead.

Accessing a variable with an __weak attribute is actually done by calling objc_loadWeak() and objc_storeWeak(), which is also expensive, so avoid using the __weak attribute.

When creating and using objects, try to avoid objects entering autoReleasepool to avoid additional resource overhead.

6. Select more efficient methods when iterating through container classes. CoreFoundation methods have higher performance than Foundation methods. Use CFArrayApplyFunction () and CFDictionaryApplyFunction () method to traverse the container classes can bring a lot of performance improvement, but will be very trouble to write code.

7. Try to use pure C functions, inline functions Using pure C functions can avoid the overhead of ObjC message sending. If C functions are small, using inline can avoid some of the overhead of function calls such as stack pops.

Before converting JSON to Model, the number of Model attributes and the number of JSON attributes are known. In this case, it will save a lot of time to select the one with a smaller number for traversal.