ViewController.m 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841
  1. //
  2. // ViewController.m
  3. // ModelBenchmark
  4. //
  5. // Created by ibireme on 15/9/18.
  6. // Copyright (c) 2015 ibireme. All rights reserved.
  7. //
  8. #import <QuartzCore/QuartzCore.h>
  9. #import "ViewController.h"
  10. #import "DateFormatter.h"
  11. #import "GitHubUser.h"
  12. #import "YYWeiboModel.h"
  13. #import "FEWeiboModel.h"
  14. #import "MTWeiboModel.h"
  15. #import "JSWeiboModel.h"
  16. #import "MJWeiboModel.h"
  17. //#import "ModelBenchmark-Swift.h"
  18. /*
  19. Benchmark: (update to 2015-09-18)
  20. YYModel: https://github.com/ibireme/YYKit
  21. Mantle: https://github.com/Mantle/Mantle
  22. JSONModel: https://github.com/icanzilb/JSONModel
  23. FastEasyMapping: https://github.com/Yalantis/FastEasyMapping
  24. MJExtension: https://github.com/CoderMJLee/MJExtension
  25. */
  26. @implementation ViewController
  27. - (void)viewDidLoad {
  28. [super viewDidLoad];
  29. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  30. [self benchmarkGithubUser];
  31. [self benchmarkWeiboStatus];
  32. [self testRobustness];
  33. });
  34. }
  35. - (void)benchmarkGithubUser {
  36. /// Benchmark swift .. too slow...
  37. /// [GithubUserBenchmark benchmark];
  38. printf("----------------------\n");
  39. printf("Benchmark (10000 times):\n");
  40. printf("GHUser from json to json archive\n");
  41. /// get json data
  42. NSString *path = [[NSBundle mainBundle] pathForResource:@"user" ofType:@"json"];
  43. NSData *data = [NSData dataWithContentsOfFile:path];
  44. NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
  45. /// Benchmark
  46. int count = 10000;
  47. NSTimeInterval begin, end;
  48. /// warm up (NSDictionary's hot cache, and JSON to model framework cache)
  49. FEMMapping *mapping = [FEGHUser defaultMapping];
  50. MTLJSONAdapter *adapter = [[MTLJSONAdapter alloc] initWithModelClass:[MTGHUser class]];
  51. @autoreleasepool {
  52. for (int i = 0; i < count; i++) {
  53. // Manually
  54. [[[[GHUser alloc] initWithJSONDictionary:json] description] length];
  55. // YYModel
  56. [YYGHUser yy_modelWithJSON:json];
  57. // FastEasyMapping
  58. [FEMDeserializer fillObject:[FEGHUser new] fromRepresentation:json mapping:mapping];
  59. // JSONModel
  60. [[[[JSGHUser alloc] initWithDictionary:json error:nil] description] length];
  61. // Mantle
  62. [adapter modelFromJSONDictionary:json error:nil];
  63. // MJExtension
  64. [MJGHUser objectWithKeyValues:json];
  65. }
  66. }
  67. /// warm up holder
  68. NSMutableArray *holder = [NSMutableArray new];
  69. for (int i = 0; i < 1800; i++) {
  70. [holder addObject:[NSDate new]];
  71. }
  72. [holder removeAllObjects];
  73. /*------------------- Manually -------------------*/
  74. {
  75. [holder removeAllObjects];
  76. begin = CACurrentMediaTime();
  77. @autoreleasepool {
  78. for (int i = 0; i < count; i++) {
  79. GHUser *user = [[GHUser alloc] initWithJSONDictionary:json];
  80. [holder addObject:user];
  81. }
  82. }
  83. end = CACurrentMediaTime();
  84. printf("Manually: %8.2f ", (end - begin) * 1000);
  85. GHUser *user = [[GHUser alloc] initWithJSONDictionary:json];
  86. if (user.userID == 0) NSLog(@"error!");
  87. if (!user.login) NSLog(@"error!");
  88. if (!user.htmlURL) NSLog(@"error");
  89. [holder removeAllObjects];
  90. begin = CACurrentMediaTime();
  91. @autoreleasepool {
  92. for (int i = 0; i < count; i++) {
  93. NSDictionary *json = [user convertToJSONDictionary];
  94. [holder addObject:json];
  95. }
  96. }
  97. end = CACurrentMediaTime();
  98. if ([NSJSONSerialization isValidJSONObject:[user convertToJSONDictionary]]) {
  99. printf("%8.2f ", (end - begin) * 1000);
  100. } else {
  101. printf(" error ");
  102. }
  103. [holder removeAllObjects];
  104. begin = CACurrentMediaTime();
  105. @autoreleasepool {
  106. for (int i = 0; i < count; i++) {
  107. NSData *data = [NSKeyedArchiver archivedDataWithRootObject:user];
  108. [holder addObject:data];
  109. }
  110. }
  111. end = CACurrentMediaTime();
  112. printf("%8.2f\n", (end - begin) * 1000);
  113. }
  114. /*------------------- YYModel -------------------*/
  115. {
  116. [holder removeAllObjects];
  117. begin = CACurrentMediaTime();
  118. @autoreleasepool {
  119. for (int i = 0; i < count; i++) {
  120. YYGHUser *user = [YYGHUser yy_modelWithJSON:json];
  121. [holder addObject:user];
  122. }
  123. }
  124. end = CACurrentMediaTime();
  125. printf("YYModel: %8.2f ", (end - begin) * 1000);
  126. YYGHUser *user = [YYGHUser yy_modelWithJSON:json];
  127. if (user.userID == 0) NSLog(@"error!");
  128. if (!user.login) NSLog(@"error!");
  129. if (!user.htmlURL) NSLog(@"error");
  130. [holder removeAllObjects];
  131. begin = CACurrentMediaTime();
  132. @autoreleasepool {
  133. for (int i = 0; i < count; i++) {
  134. NSDictionary *json = [user yy_modelToJSONObject];
  135. [holder addObject:json];
  136. }
  137. }
  138. end = CACurrentMediaTime();
  139. if ([NSJSONSerialization isValidJSONObject:[user yy_modelToJSONObject]]) {
  140. printf("%8.2f ", (end - begin) * 1000);
  141. } else {
  142. printf(" error ");
  143. }
  144. [holder removeAllObjects];
  145. begin = CACurrentMediaTime();
  146. @autoreleasepool {
  147. for (int i = 0; i < count; i++) {
  148. NSData *data = [NSKeyedArchiver archivedDataWithRootObject:user];
  149. [holder addObject:data];
  150. }
  151. }
  152. end = CACurrentMediaTime();
  153. printf("%8.2f\n", (end - begin) * 1000);
  154. }
  155. /*------------------- FastEasyMapping -------------------*/
  156. {
  157. [holder removeAllObjects];
  158. begin = CACurrentMediaTime();
  159. @autoreleasepool {
  160. for (int i = 0; i < count; i++) {
  161. FEGHUser *user = [FEGHUser new];
  162. [FEMDeserializer fillObject:user fromRepresentation:json mapping:mapping];
  163. [user class];
  164. }
  165. }
  166. end = CACurrentMediaTime();
  167. printf("FastEasyMapping: %8.2f ", (end - begin) * 1000);
  168. FEGHUser *user = [FEGHUser new];
  169. [FEMDeserializer fillObject:user fromRepresentation:json mapping:mapping];
  170. if (user.userID == 0) NSLog(@"error!");
  171. if (!user.login) NSLog(@"error!");
  172. if (!user.htmlURL) NSLog(@"error");
  173. [holder removeAllObjects];
  174. begin = CACurrentMediaTime();
  175. @autoreleasepool {
  176. for (int i = 0; i < count; i++) {
  177. NSDictionary *json = [FEMSerializer serializeObject:user usingMapping:mapping];
  178. [holder addObject:json];
  179. }
  180. }
  181. end = CACurrentMediaTime();
  182. if ([NSJSONSerialization isValidJSONObject: [FEMSerializer serializeObject:user usingMapping:mapping]]) {
  183. printf("%8.2f ", (end - begin) * 1000);
  184. } else {
  185. printf(" error ");
  186. }
  187. // FastEasyMapping does not support NSCoding?
  188. printf(" N/A\n");
  189. }
  190. /*------------------- JSONModel -------------------*/
  191. {
  192. [holder removeAllObjects];
  193. begin = CACurrentMediaTime();
  194. @autoreleasepool {
  195. for (int i = 0; i < count; i++) {
  196. JSGHUser *user = [[JSGHUser alloc] initWithDictionary:json error:nil];
  197. [user class];
  198. }
  199. }
  200. end = CACurrentMediaTime();
  201. printf("JSONModel: %8.2f ", (end - begin) * 1000);
  202. JSGHUser *user = [[JSGHUser alloc] initWithDictionary:json error:nil];
  203. if (user.userID == 0) NSLog(@"error!");
  204. if (!user.login) NSLog(@"error!");
  205. if (!user.htmlURL) NSLog(@"error");
  206. [holder removeAllObjects];
  207. begin = CACurrentMediaTime();
  208. @autoreleasepool {
  209. for (int i = 0; i < count; i++) {
  210. NSDictionary *json = [user toDictionary];
  211. [holder addObject:json];
  212. }
  213. }
  214. end = CACurrentMediaTime();
  215. if ([NSJSONSerialization isValidJSONObject:[user toDictionary]]) {
  216. printf("%8.2f ", (end - begin) * 1000);
  217. } else {
  218. printf(" error ");
  219. }
  220. [holder removeAllObjects];
  221. begin = CACurrentMediaTime();
  222. @autoreleasepool {
  223. for (int i = 0; i < count; i++) {
  224. NSData *data = [NSKeyedArchiver archivedDataWithRootObject:user];
  225. [holder addObject:data];
  226. }
  227. }
  228. end = CACurrentMediaTime();
  229. printf("%8.2f\n", (end - begin) * 1000);
  230. }
  231. /*------------------- Mantle -------------------*/
  232. {
  233. [holder removeAllObjects];
  234. begin = CACurrentMediaTime();
  235. @autoreleasepool {
  236. for (int i = 0; i < count; i++) {
  237. MTGHUser *user = [adapter modelFromJSONDictionary:json error:nil];
  238. [user class];
  239. }
  240. }
  241. end = CACurrentMediaTime();
  242. printf("Mantle: %8.2f ", (end - begin) * 1000);
  243. MTGHUser *user = [adapter modelFromJSONDictionary:json error:nil];
  244. if (user.userID == 0) NSLog(@"error!");
  245. if (!user.login) NSLog(@"error!");
  246. if (!user.htmlURL) NSLog(@"error");
  247. [holder removeAllObjects];
  248. begin = CACurrentMediaTime();
  249. @autoreleasepool {
  250. for (int i = 0; i < count; i++) {
  251. NSDictionary *json = [adapter JSONDictionaryFromModel:user error:nil];
  252. [holder addObject:json];
  253. }
  254. }
  255. end = CACurrentMediaTime();
  256. if ([NSJSONSerialization isValidJSONObject:[adapter JSONDictionaryFromModel:user error:nil]]) {
  257. printf("%8.2f ", (end - begin) * 1000);
  258. } else {
  259. printf(" error ");
  260. }
  261. [holder removeAllObjects];
  262. begin = CACurrentMediaTime();
  263. @autoreleasepool {
  264. for (int i = 0; i < count; i++) {
  265. NSData *data = [NSKeyedArchiver archivedDataWithRootObject:user];
  266. [holder addObject:data];
  267. }
  268. }
  269. end = CACurrentMediaTime();
  270. printf("%8.2f\n", (end - begin) * 1000);
  271. }
  272. /*------------------- MJExtension -------------------*/
  273. {
  274. [holder removeAllObjects];
  275. begin = CACurrentMediaTime();
  276. @autoreleasepool {
  277. for (int i = 0; i < count; i++) {
  278. MJGHUser *user = [MJGHUser objectWithKeyValues:json];
  279. [user class];
  280. }
  281. }
  282. end = CACurrentMediaTime();
  283. printf("MJExtension: %8.2f ", (end - begin) * 1000);
  284. MJGHUser *user = [MJGHUser objectWithKeyValues:json];
  285. if (user.userID == 0) NSLog(@"error!");
  286. if (!user.login) NSLog(@"error!");
  287. if (!user.htmlURL) NSLog(@"error");
  288. [holder removeAllObjects];
  289. begin = CACurrentMediaTime();
  290. @autoreleasepool {
  291. for (int i = 0; i < count; i++) {
  292. NSDictionary *json = [user JSONObject];
  293. [holder addObject:json];
  294. }
  295. }
  296. end = CACurrentMediaTime();
  297. if ([NSJSONSerialization isValidJSONObject:[user JSONObject]]) {
  298. printf("%8.2f ", (end - begin) * 1000);
  299. } else {
  300. printf(" error ");
  301. }
  302. [holder removeAllObjects];
  303. begin = CACurrentMediaTime();
  304. @autoreleasepool {
  305. for (int i = 0; i < count; i++) {
  306. NSData *data = [NSKeyedArchiver archivedDataWithRootObject:user];
  307. [holder addObject:data];
  308. }
  309. }
  310. end = CACurrentMediaTime();
  311. printf("%8.2f\n", (end - begin) * 1000);
  312. }
  313. printf("----------------------\n");
  314. printf("\n");
  315. }
  316. - (void)benchmarkWeiboStatus {
  317. printf("----------------------\n");
  318. printf("Benchmark (1000 times):\n");
  319. printf("WeiboStatus from json to json archive\n");
  320. /// get json data
  321. NSString *path = [[NSBundle mainBundle] pathForResource:@"weibo" ofType:@"json"];
  322. NSData *data = [NSData dataWithContentsOfFile:path];
  323. NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
  324. /// Benchmark
  325. int count = 1000;
  326. NSTimeInterval begin, end;
  327. /// warm up (NSDictionary's hot cache, and JSON to model framework cache)
  328. FEMMapping *mapping = [FEWeiboStatus defaultMapping];
  329. MTLJSONAdapter *adapter = [[MTLJSONAdapter alloc] initWithModelClass:[MTWeiboStatus class]];
  330. @autoreleasepool {
  331. for (int i = 0; i < count * 2; i++) {
  332. // YYModel
  333. [YYWeiboStatus yy_modelWithJSON:json];
  334. // FastEasyMapping
  335. [FEMDeserializer fillObject:[FEWeiboStatus new] fromRepresentation:json mapping:mapping];
  336. // JSONModel
  337. [[[JSWeiboStatus alloc] initWithDictionary:json error:nil] description];
  338. // Mantle
  339. [adapter modelFromJSONDictionary:json error:nil];
  340. // MJExtension
  341. [MJWeiboStatus objectWithKeyValues:json];
  342. }
  343. }
  344. /// warm up holder
  345. NSMutableArray *holder = [NSMutableArray new];
  346. for (int i = 0; i < count; i++) {
  347. [holder addObject:[NSData new]];
  348. }
  349. [holder removeAllObjects];
  350. /*------------------- YYModel -------------------*/
  351. {
  352. [holder removeAllObjects];
  353. begin = CACurrentMediaTime();
  354. @autoreleasepool {
  355. for (int i = 0; i < count; i++) {
  356. YYWeiboStatus *feed = [YYWeiboStatus yy_modelWithJSON:json];
  357. [holder addObject:feed];
  358. }
  359. }
  360. end = CACurrentMediaTime();
  361. printf("YYModel: %8.2f ", (end - begin) * 1000);
  362. YYWeiboStatus *feed = [YYWeiboStatus yy_modelWithJSON:json];
  363. [holder removeAllObjects];
  364. begin = CACurrentMediaTime();
  365. @autoreleasepool {
  366. for (int i = 0; i < count; i++) {
  367. NSDictionary *json = [feed yy_modelToJSONObject];
  368. [holder addObject:json];
  369. }
  370. }
  371. end = CACurrentMediaTime();
  372. if ([NSJSONSerialization isValidJSONObject:[feed yy_modelToJSONObject]]) {
  373. printf("%8.2f ", (end - begin) * 1000);
  374. } else {
  375. printf(" error ");
  376. }
  377. [holder removeAllObjects];
  378. begin = CACurrentMediaTime();
  379. @autoreleasepool {
  380. for (int i = 0; i < count; i++) {
  381. NSData *data = [NSKeyedArchiver archivedDataWithRootObject:feed];
  382. [holder addObject:data];
  383. }
  384. }
  385. end = CACurrentMediaTime();
  386. printf("%8.2f\n", (end - begin) * 1000);
  387. }
  388. /*------------------- FastEasyMapping -------------------*/
  389. {
  390. [holder removeAllObjects];
  391. begin = CACurrentMediaTime();
  392. @autoreleasepool {
  393. for (int i = 0; i < count; i++) {
  394. FEWeiboStatus *feed = [FEWeiboStatus new];
  395. [FEMDeserializer fillObject:feed fromRepresentation:json mapping:mapping];
  396. [holder addObject:feed];
  397. }
  398. }
  399. end = CACurrentMediaTime();
  400. printf("FastEasyMapping: %8.2f ", (end - begin) * 1000);
  401. FEWeiboStatus *feed = [FEWeiboStatus new];
  402. [FEMDeserializer fillObject:feed fromRepresentation:json mapping:mapping];
  403. [holder removeAllObjects];
  404. begin = CACurrentMediaTime();
  405. @autoreleasepool {
  406. for (int i = 0; i < count; i++) {
  407. NSDictionary *json = [FEMSerializer serializeObject:feed usingMapping:mapping];
  408. [holder addObject:json];
  409. }
  410. }
  411. end = CACurrentMediaTime();
  412. if ([NSJSONSerialization isValidJSONObject: [FEMSerializer serializeObject:feed usingMapping:mapping]]) {
  413. printf("%8.2f ", (end - begin) * 1000);
  414. } else {
  415. printf(" error ");
  416. }
  417. // FastEasyMapping does not support NSCoding?
  418. printf(" N/A\n");
  419. }
  420. /*------------------- JSONModel -------------------*/
  421. {
  422. [holder removeAllObjects];
  423. begin = CACurrentMediaTime();
  424. @autoreleasepool {
  425. for (int i = 0; i < count; i++) {
  426. JSWeiboStatus *feed = [[JSWeiboStatus alloc] initWithDictionary:json error:nil];
  427. [holder addObject:feed];
  428. }
  429. }
  430. end = CACurrentMediaTime();
  431. printf("JSONModel: %8.2f ", (end - begin) * 1000);
  432. JSWeiboStatus *feed = [[JSWeiboStatus alloc] initWithDictionary:json error:nil];
  433. [holder removeAllObjects];
  434. begin = CACurrentMediaTime();
  435. @autoreleasepool {
  436. for (int i = 0; i < count; i++) {
  437. NSDictionary *json = [feed toDictionary];
  438. [holder addObject:json];
  439. }
  440. }
  441. end = CACurrentMediaTime();
  442. if ([NSJSONSerialization isValidJSONObject:[feed toDictionary]]) {
  443. printf("%8.2f ", (end - begin) * 1000);
  444. } else {
  445. printf(" error ");
  446. }
  447. [holder removeAllObjects];
  448. begin = CACurrentMediaTime();
  449. @autoreleasepool {
  450. for (int i = 0; i < count; i++) {
  451. NSData *data = [NSKeyedArchiver archivedDataWithRootObject:feed];
  452. [holder addObject:data];
  453. }
  454. }
  455. end = CACurrentMediaTime();
  456. printf("%8.2f\n", (end - begin) * 1000);
  457. }
  458. /*------------------- Mantle -------------------*/
  459. {
  460. [holder removeAllObjects];
  461. begin = CACurrentMediaTime();
  462. @autoreleasepool {
  463. for (int i = 0; i < count; i++) {
  464. MTWeiboStatus *feed = [adapter modelFromJSONDictionary:json error:nil];
  465. [holder addObject:feed];
  466. }
  467. }
  468. end = CACurrentMediaTime();
  469. printf("Mantle: %8.2f ", (end - begin) * 1000);
  470. MTWeiboStatus *feed = [adapter modelFromJSONDictionary:json error:nil];
  471. [holder removeAllObjects];
  472. begin = CACurrentMediaTime();
  473. @autoreleasepool {
  474. for (int i = 0; i < count; i++) {
  475. NSDictionary *json = [adapter JSONDictionaryFromModel:feed error:nil];
  476. [holder addObject:json];
  477. }
  478. }
  479. end = CACurrentMediaTime();
  480. if ([NSJSONSerialization isValidJSONObject:[adapter JSONDictionaryFromModel:feed error:nil]]) {
  481. printf("%8.2f ", (end - begin) * 1000);
  482. } else {
  483. printf(" error ");
  484. }
  485. [holder removeAllObjects];
  486. begin = CACurrentMediaTime();
  487. @autoreleasepool {
  488. for (int i = 0; i < count; i++) {
  489. NSData *data = [NSKeyedArchiver archivedDataWithRootObject:feed];
  490. [holder addObject:data];
  491. }
  492. }
  493. end = CACurrentMediaTime();
  494. printf("%8.2f\n", (end - begin) * 1000);
  495. }
  496. /*------------------- MJExtension -------------------*/
  497. {
  498. [holder removeAllObjects];
  499. begin = CACurrentMediaTime();
  500. @autoreleasepool {
  501. for (int i = 0; i < count; i++) {
  502. MJWeiboStatus *feed = [MJWeiboStatus objectWithKeyValues:json];
  503. [holder addObject:feed];
  504. }
  505. }
  506. end = CACurrentMediaTime();
  507. printf("MJExtension: %8.2f ", (end - begin) * 1000);
  508. MJWeiboStatus *feed = [MJWeiboStatus objectWithKeyValues:json];
  509. [holder removeAllObjects];
  510. begin = CACurrentMediaTime();
  511. @autoreleasepool {
  512. for (int i = 0; i < count; i++) {
  513. NSDictionary *json = [feed JSONObject];
  514. [holder addObject:json];
  515. }
  516. }
  517. end = CACurrentMediaTime();
  518. if ([NSJSONSerialization isValidJSONObject:[feed JSONObject]]) {
  519. printf("%8.2f ", (end - begin) * 1000);
  520. } else {
  521. printf(" error ");
  522. }
  523. [holder removeAllObjects];
  524. begin = CACurrentMediaTime();
  525. @autoreleasepool {
  526. for (int i = 0; i < count; i++) {
  527. NSData *data = [NSKeyedArchiver archivedDataWithRootObject:feed];
  528. [holder addObject:data];
  529. }
  530. }
  531. end = CACurrentMediaTime();
  532. printf("%8.2f\n", (end - begin) * 1000);
  533. }
  534. printf("----------------------\n");
  535. printf("\n");
  536. }
  537. - (void)testRobustness {
  538. {
  539. printf("----------------------\n");
  540. printf("The property is NSString, but the json value is number:\n");
  541. NSString *jsonStr = @"{\"type\":1}";
  542. NSDictionary *json = [NSJSONSerialization JSONObjectWithData:[jsonStr dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:nil];
  543. void (^logError)(NSString *model, id user) = ^(NSString *model, id user){
  544. printf("%s ",model.UTF8String);
  545. if (!user) {
  546. printf("⚠️ model is nil\n");
  547. } else {
  548. NSString *type = ((YYGHUser *)user).type;
  549. if (type == nil || type == (id)[NSNull null]) {
  550. printf("⚠️ property is nil\n");
  551. } else if ([type isKindOfClass:[NSString class]]) {
  552. printf("✅ property is %s\n",NSStringFromClass(type.class).UTF8String);
  553. } else {
  554. printf("🚫 property is %s\n",NSStringFromClass(type.class).UTF8String);
  555. }
  556. }
  557. };
  558. // YYModel
  559. YYGHUser *yyUser = [YYGHUser yy_modelWithJSON:json];
  560. logError(@"YYModel: ", yyUser);
  561. // FastEasyMapping
  562. FEGHUser *feUser = [FEGHUser new];
  563. FEMMapping *mapping = [FEGHUser defaultMapping];
  564. [FEMDeserializer fillObject:feUser fromRepresentation:json mapping:mapping];
  565. logError(@"FastEasyMapping:", feUser);
  566. // JSONModel
  567. JSGHUser *jsUser = [[JSGHUser alloc] initWithDictionary:json error:nil];
  568. logError(@"JSONModel: ", jsUser);
  569. // Mantle
  570. MTLJSONAdapter *adapter = [[MTLJSONAdapter alloc] initWithModelClass:[MTGHUser class]];
  571. MTGHUser *mtUser = [adapter modelFromJSONDictionary:json error:nil];
  572. logError(@"Mantle: ", mtUser);
  573. // MJExtension
  574. MJGHUser *mjUser = [MJGHUser objectWithKeyValues:json];
  575. logError(@"MJExtension: ", mjUser);
  576. printf("\n");
  577. }
  578. {
  579. printf("----------------------\n");
  580. printf("The property is int, but the json value is string:\n");
  581. NSString *jsonStr = @"{\"followers\":\"100\"}";
  582. NSDictionary *json = [NSJSONSerialization JSONObjectWithData:[jsonStr dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:nil];
  583. void (^logError)(NSString *model, id user) = ^(NSString *model, id user){
  584. printf("%s ",model.UTF8String);
  585. if (!user) {
  586. printf("⚠️ model is nil\n");
  587. } else {
  588. UInt32 num = ((YYGHUser *)user).followers;
  589. if (num != 100) {
  590. printf("🚫 property is %u\n",(unsigned int)num);
  591. } else {
  592. printf("✅ property is %u\n",(unsigned int)num);
  593. }
  594. }
  595. };
  596. // YYModel
  597. YYGHUser *yyUser = [YYGHUser yy_modelWithJSON:json];
  598. logError(@"YYModel: ", yyUser);
  599. // FastEasyMapping
  600. @try {
  601. FEGHUser *feUser = [FEGHUser new];
  602. FEMMapping *mapping = [FEGHUser defaultMapping];
  603. [FEMDeserializer fillObject:feUser fromRepresentation:json mapping:mapping];
  604. logError(@"FastEasyMapping:", feUser);
  605. }
  606. @catch (NSException *exception) {
  607. printf("FastEasyMapping: 🚫crash\n");
  608. }
  609. @try {
  610. // JSONModel
  611. JSGHUser *jsUser = [[JSGHUser alloc] initWithDictionary:json error:nil];
  612. logError(@"JSONModel: ", jsUser);
  613. }
  614. @catch (NSException *exception) {
  615. printf("JSONModel: 🚫crash\n");
  616. }
  617. // Mantle
  618. MTLJSONAdapter *adapter = [[MTLJSONAdapter alloc] initWithModelClass:[MTGHUser class]];
  619. MTGHUser *mtUser = [adapter modelFromJSONDictionary:json error:nil];
  620. logError(@"Mantle: ", mtUser);
  621. // MJExtension
  622. MJGHUser *mjUser = [MJGHUser objectWithKeyValues:json];
  623. logError(@"MJExtension: ", mjUser);
  624. }
  625. {
  626. printf("----------------------\n");
  627. printf("The property is NSDate, and the json value is string:\n");
  628. NSString *jsonStr = @"{\"updated_at\":\"2009-04-02T03:35:22Z\"}";
  629. NSDictionary *json = [NSJSONSerialization JSONObjectWithData:[jsonStr dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:nil];
  630. void (^logError)(NSString *model, id user) = ^(NSString *model, id user){
  631. printf("%s ",model.UTF8String);
  632. if (!user) {
  633. printf("⚠️ model is nil\n");
  634. } else {
  635. NSDate *date = ((YYGHUser *)user).updatedAt;
  636. if (date == nil || date == (id)[NSNull null]) {
  637. printf("⚠️ property is nil\n");
  638. } else if ([date isKindOfClass:[NSDate class]]) {
  639. printf("✅ property is %s\n",NSStringFromClass(date.class).UTF8String);
  640. } else {
  641. printf("🚫 property is %s\n",NSStringFromClass(date.class).UTF8String);
  642. }
  643. }
  644. };
  645. // YYModel
  646. YYGHUser *yyUser = [YYGHUser yy_modelWithJSON:json];
  647. logError(@"YYModel: ", yyUser);
  648. // FastEasyMapping
  649. FEGHUser *feUser = [FEGHUser new];
  650. FEMMapping *mapping = [FEGHUser defaultMapping];
  651. [FEMDeserializer fillObject:feUser fromRepresentation:json mapping:mapping];
  652. logError(@"FastEasyMapping:", feUser);
  653. // JSONModel
  654. JSGHUser *jsUser = [[JSGHUser alloc] initWithDictionary:json error:nil];
  655. logError(@"JSONModel: ", jsUser);
  656. // Mantle
  657. MTLJSONAdapter *adapter = [[MTLJSONAdapter alloc] initWithModelClass:[MTGHUser class]];
  658. MTGHUser *mtUser = [adapter modelFromJSONDictionary:json error:nil];
  659. logError(@"Mantle: ", mtUser);
  660. // MJExtension
  661. MJGHUser *mjUser = [MJGHUser objectWithKeyValues:json];
  662. logError(@"MJExtension: ", mjUser);
  663. printf("\n");
  664. }
  665. {
  666. printf("----------------------\n");
  667. printf("The property is NSValue, and the json value is string:\n");
  668. NSString *jsonStr = @"{\"test\":\"https://github.com\"}";
  669. NSDictionary *json = [NSJSONSerialization JSONObjectWithData:[jsonStr dataUsingEncoding:NSUTF8StringEncoding] options:kNilOptions error:nil];
  670. void (^logError)(NSString *model, id user) = ^(NSString *model, id user){
  671. printf("%s ",model.UTF8String);
  672. if (!user) {
  673. printf("⚠️ model is nil\n");
  674. } else {
  675. NSValue *valur = ((YYGHUser *)user).test;
  676. if (valur == nil || valur == (id)[NSNull null]) {
  677. printf("✅ property is nil\n");
  678. } else if ([valur isKindOfClass:[NSURLRequest class]]) {
  679. printf("✅ property is %s\n",NSStringFromClass(valur.class).UTF8String);
  680. } else {
  681. printf("🚫 property is %s\n",NSStringFromClass(valur.class).UTF8String);
  682. }
  683. }
  684. };
  685. // YYModel
  686. YYGHUser *yyUser = [YYGHUser yy_modelWithJSON:json];
  687. logError(@"YYModel: ", yyUser);
  688. // FastEasyMapping
  689. FEGHUser *feUser = [FEGHUser new];
  690. FEMMapping *mapping = [FEGHUser defaultMapping];
  691. [FEMDeserializer fillObject:feUser fromRepresentation:json mapping:mapping];
  692. logError(@"FastEasyMapping:", feUser);
  693. @try {
  694. // JSONModel
  695. JSGHUser *jsUser = [[JSGHUser alloc] initWithDictionary:json error:nil];
  696. logError(@"JSONModel: ", jsUser);
  697. }
  698. @catch (NSException *exception) {
  699. printf("JSONModel: 🚫crash\n");
  700. }
  701. // Mantle
  702. MTLJSONAdapter *adapter = [[MTLJSONAdapter alloc] initWithModelClass:[MTGHUser class]];
  703. MTGHUser *mtUser = [adapter modelFromJSONDictionary:json error:nil];
  704. logError(@"Mantle: ", mtUser);
  705. // MJExtension
  706. MJGHUser *mjUser = [MJGHUser objectWithKeyValues:json];
  707. logError(@"MJExtension: ", mjUser);
  708. printf("\n");
  709. }
  710. }
  711. @end