NSObject+Json.m 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621
  1. //
  2. // NSObject+Json.m
  3. //
  4. //
  5. // Created by Alexi on 12-11-15.
  6. // Copyright (c) 2012年 . All rights reserved.
  7. //
  8. #import "NSObject+Json.h"
  9. #import <objc/runtime.h>
  10. #import "JSONKit.h"
  11. #import "IOSDeviceConfig.h"
  12. @implementation NSObject (Json)
  13. #define kServiceTag_ID @"id"
  14. - (void)setIdPropertyValue:(id)idkeyValue
  15. {
  16. // for the subclass to do
  17. }
  18. /*
  19. * 对于格式如下的方法,使用以下接口进行反序化
  20. * [{itemClass对应的json串},{itemClass对应的json串}...]
  21. * 参数说明:
  22. * itemClass: json列表中单个数据对要反序列化成的对像类型
  23. * arraydict: json列表
  24. */
  25. + (NSMutableArray *)loadItem:(Class)itemClass fromArrayDictionary:(NSArray *)arraydict
  26. {
  27. NSMutableArray *array = [[NSMutableArray alloc] init];
  28. for (NSDictionary *dic in arraydict ) {
  29. if (dic) {
  30. id value = [NSObject parse:itemClass dictionary:dic];
  31. [array addObject:value];
  32. }
  33. }
  34. return CommonReturnAutoReleased(array);
  35. }
  36. /*
  37. *
  38. */
  39. - (void)setValueForPropertyValue:(id)idkeyValue forKey:(NSString *)key propertyClass:(Class)cls tagretClass:(Class)targetCls
  40. {
  41. if ([idkeyValue isKindOfClass:[NSDictionary class]])
  42. {
  43. // 说明要赋值的属性是NSObject的子类
  44. id value = [NSObject parse:targetCls dictionary:idkeyValue itemClass:cls];
  45. [self setValue:value forKey:key];
  46. }
  47. else if ([idkeyValue isKindOfClass:[NSArray class]])
  48. {
  49. // NSMutableArray *array = [[NSMutableArray alloc] init];
  50. // for (NSDictionary *dic in idkeyValue ) {
  51. // if (dic) {
  52. // id value = [NSObject parse:cls dictionary:dic];
  53. // [array addObject:value];
  54. // }
  55. // }
  56. //
  57. // [self setValue:array forKey:key];
  58. // [array release];
  59. // 说明要赋值的属性是一个列表
  60. NSMutableArray *arrayValue = (NSMutableArray *)[NSObject loadItem:cls fromArrayDictionary:idkeyValue];
  61. [self setValue:arrayValue forKey:key];
  62. }
  63. }
  64. // 遍历
  65. - (void)enumerateProperty:(NSString *)propertyName value:(id)idvalue propertyDictionary:(NSDictionary *)propertyKeys
  66. {
  67. if ([idvalue isKindOfClass:[NSNull class]])
  68. {
  69. NSString *proClsName = [propertyKeys objectForKey:propertyName];
  70. if ([proClsName hasPrefix:@"T@"])
  71. {
  72. [self setValue:nil forKey:propertyName];
  73. }
  74. else
  75. {
  76. NSNumber *num = [NSNumber numberWithInteger:0];
  77. [self setValue:num forKey:propertyName];
  78. }
  79. }
  80. else
  81. {
  82. if (idvalue)
  83. {
  84. NSString *proClsName = [propertyKeys objectForKey:propertyName];
  85. if ([proClsName hasPrefix:@"T@"])
  86. {
  87. NSRange range = [proClsName rangeOfString:@"\""];
  88. NSString *test = [proClsName substringFromIndex:range.location+1];
  89. range = [test rangeOfString:@"\""];
  90. NSString *realClassName = [test substringToIndex:range.location];
  91. Class proCls = NSClassFromString(realClassName);
  92. if ([idvalue isKindOfClass:proCls] && ![idvalue isKindOfClass:[NSMutableArray class]] && ![idvalue isKindOfClass:[NSMutableDictionary class]])
  93. {
  94. [self setValue:idvalue forKey:propertyName];
  95. }
  96. else
  97. {
  98. [self setValueForPropertyValue:idvalue forKey:propertyName propertyClass:proCls tagretClass:proCls];
  99. }
  100. }
  101. else
  102. {
  103. if ([idvalue isKindOfClass:[NSDecimalNumber class]]) {
  104. NSDecimalNumber *num = (NSDecimalNumber *)idvalue;
  105. [self setValue:num forKey:propertyName];
  106. }
  107. else
  108. {
  109. NSNumber *num = (NSNumber *)idvalue;
  110. [self setValue:num forKey:propertyName];
  111. }
  112. }
  113. }
  114. }
  115. }
  116. + (id)parse:(Class)aClass dictionary:(NSDictionary *)dict
  117. {
  118. id aClassInstance = [[aClass alloc] init];
  119. CommonAutoRelease(aClassInstance);
  120. // 因JSON返回的字段中有id
  121. // 所以对此数据作特处理
  122. id idTagValue = [dict objectForKey:kServiceTag_ID];
  123. if (idTagValue) {
  124. [aClassInstance setIdPropertyValue:idTagValue];
  125. }
  126. // 将返回的Json键与aClassInstance的属性列表进行一次对比,找出要赋值的属性,以减少不必要的运算
  127. NSDictionary *propertyKeys = [aClassInstance enumerateKeysInDictionary:dict];
  128. CommonRetain(propertyKeys);
  129. NSArray *propertyKeysArray = [propertyKeys allKeys];
  130. // 逐一对相关的属性进行设置
  131. for (unsigned int i = 0 ; i < propertyKeysArray.count; i++ )
  132. {
  133. NSString *propertyName = [propertyKeysArray objectAtIndex:i];
  134. id idvalue = [dict objectForKey:propertyName];
  135. // propertyName:要设置的属性名
  136. // idvalue:对应的值
  137. [aClassInstance enumerateProperty:propertyName value:idvalue propertyDictionary:propertyKeys];
  138. }
  139. CommonRelease(propertyKeys);
  140. return aClassInstance;
  141. }
  142. - (NSMutableDictionary *)propertyListOfClass:(Class)class
  143. {
  144. NSMutableDictionary *dic = [NSMutableDictionary dictionary];
  145. unsigned int propertyCount = 0;
  146. objc_property_t *propertyList = class_copyPropertyList(class, &propertyCount);
  147. for (unsigned int i = 0 ; i < propertyCount; i++ )
  148. {
  149. const char *pcName = property_getName(propertyList[i]);
  150. NSString *propertyName = [NSString stringWithCString:pcName encoding:NSUTF8StringEncoding];
  151. const char *proClsNameCStr = property_getAttributes(propertyList[i]);
  152. NSString *proClsName = [NSString stringWithCString:proClsNameCStr encoding:NSUTF8StringEncoding];
  153. [dic setObject:proClsName forKey:propertyName];
  154. }
  155. free(propertyList);
  156. if (class != [NSObject class])
  157. {
  158. // 去掉NSObject里面的属性
  159. NSMutableDictionary *ObjectClass = [self propertyListOfClass:[NSObject class]];
  160. [dic removeObjectsForKeys:[ObjectClass allKeys]];
  161. // iOS8以前dic会加上这几个不用的键值 @[@"debugDescription", @"description", @"hash", @"superclass"]
  162. if (![IOSDeviceConfig sharedConfig].isIOS7Later)
  163. {
  164. [dic removeObjectsForKeys:@[@"debugDescription", @"description", @"hash", @"superclass"]];
  165. }
  166. // {
  167. // debugDescription = "T@\"NSString\",R,C";
  168. // description = "T@\"NSString\",R,C";
  169. // hash = "TQ,R";
  170. // pageIndex = "Tq,N,V_pageIndex";
  171. // pageSize = "Tq,N,V_pageSize";
  172. // superclass = "T#,R";
  173. // }
  174. }
  175. return dic;
  176. }
  177. // 返回class的所有属性列表(包括当前类至NSObject类的之间所有继承关系对象的列表)
  178. - (void)propertyListOfClass:(Class)class propertyList:(NSMutableDictionary *)propertyDic
  179. {
  180. if (class == [NSObject class])
  181. {
  182. return;
  183. }
  184. else
  185. {
  186. // 添加class属性列表到返回结果里面
  187. NSDictionary *selfDic = [self propertyListOfClass:class];
  188. [propertyDic addEntriesFromDictionary:selfDic];
  189. // 继续查找class的父类
  190. Class superClass = class_getSuperclass(class);
  191. [self propertyListOfClass:superClass propertyList:propertyDic];
  192. }
  193. }
  194. // 通过返回的Json字典valueDict的keys,过滤出需要设置的属性名名称及对应的类型
  195. // 返回:过滤后需要设置的()
  196. - (NSDictionary *)enumerateKeysInDictionary:(NSDictionary *)valueDict
  197. {
  198. NSUInteger propertyCount = 0;
  199. NSMutableDictionary *propertyKeys = [[NSMutableDictionary alloc] init];
  200. CommonAutoRelease(propertyKeys);
  201. NSMutableDictionary *dic = [NSMutableDictionary dictionary];
  202. [self propertyListOfClass:[self class] propertyList:dic];
  203. NSArray *dicKeys = [dic allKeys];
  204. propertyCount = dicKeys.count;
  205. NSArray *valueDictKeys = [valueDict allKeys];
  206. for (int i = 0; i < propertyCount; i++) {
  207. NSString *propertyName = [dicKeys objectAtIndex:i];
  208. if ([valueDictKeys containsObject:propertyName])
  209. {
  210. [propertyKeys setObject:[dic valueForKey:propertyName] forKey:propertyName];
  211. }
  212. }
  213. return propertyKeys;
  214. }
  215. - (void)enumerateProperty:(NSString *)propertyName value:(id)idvalue propertyDictionary:(NSDictionary *)propertyKeys itemClass:(Class)itemClass
  216. {
  217. if ([idvalue isKindOfClass:[NSNull class]])
  218. {
  219. [self setValue:nil forKey:propertyName];
  220. }
  221. else
  222. {
  223. if (idvalue)
  224. {
  225. NSString *proClsName = [propertyKeys objectForKey:propertyName];
  226. if ([proClsName hasPrefix:@"T@"])
  227. {
  228. NSRange range = [proClsName rangeOfString:@"\""];
  229. NSString *test = [proClsName substringFromIndex:range.location+1];
  230. range = [test rangeOfString:@"\""];
  231. NSString *realClassName = [test substringToIndex:range.location];
  232. Class proCls = NSClassFromString(realClassName);
  233. if ([idvalue isKindOfClass:proCls] && ![idvalue isKindOfClass:[NSMutableArray class]] && ![idvalue isKindOfClass:[NSMutableDictionary class]])
  234. {
  235. [self setValue:idvalue forKey:propertyName];
  236. }
  237. else
  238. {
  239. [self setValueForPropertyValue:idvalue forKey:propertyName propertyClass:itemClass tagretClass:proCls];
  240. }
  241. }
  242. else
  243. {
  244. if ([idvalue isKindOfClass:[NSDecimalNumber class]]) {
  245. NSDecimalNumber *num = (NSDecimalNumber *)idvalue;
  246. [self setValue:num forKey:propertyName];
  247. }
  248. else
  249. {
  250. NSNumber *num = (NSNumber *)idvalue;
  251. [self setValue:num forKey:propertyName];
  252. }
  253. }
  254. }
  255. }
  256. }
  257. + (id)parse:(Class)aClass dictionary:(NSDictionary *)dict itemClass:(Class)itemClass
  258. {
  259. id aClassInstance = [[aClass alloc] init];
  260. CommonAutoRelease(aClassInstance);
  261. // 因JSON返回的字段中有id
  262. // 所以对此数据作特处理
  263. id idTagValue = [dict objectForKey:kServiceTag_ID];
  264. if (idTagValue) {
  265. [aClassInstance setIdPropertyValue:idTagValue];
  266. }
  267. NSDictionary *propertyKeys = [aClassInstance enumerateKeysInDictionary:dict];
  268. CommonRetain(propertyKeys);
  269. NSArray *propertyKeysArray = [propertyKeys allKeys];
  270. for (unsigned int i = 0 ; i < propertyKeysArray.count; i++ )
  271. {
  272. NSString *propertyName = [propertyKeysArray objectAtIndex:i];
  273. id idvalue = [dict objectForKey:propertyName];
  274. [aClassInstance enumerateProperty:propertyName value:idvalue propertyDictionary:propertyKeys itemClass:itemClass];
  275. }
  276. CommonRelease(propertyKeys);
  277. // [propertyKeys release];
  278. return aClassInstance;
  279. }
  280. + (id)parse:(Class)aClass jsonString:(NSString *)json
  281. {
  282. NSDictionary *dic = [json objectFromJSONString];
  283. CustomMessageModel *customMessageModel = [CustomMessageModel mj_objectWithKeyValues:json];
  284. if (customMessageModel.type == 82) {
  285. NSLog(@"收到广播消息了");
  286. }
  287. return dic ? [NSObject parse:aClass dictionary:dic] : nil;
  288. }
  289. + (id)parse:(Class)aClass jsonString:(NSString *)json itemClass:(Class)itemClass
  290. {
  291. NSDictionary *dic = [json objectFromJSONString];
  292. return dic ? [NSObject parse:aClass dictionary:dic itemClass:itemClass] : nil;
  293. }
  294. + (NSMutableArray *)loadItem:(Class)itemClass fromDictionary:(NSArray *)arraydict
  295. {
  296. NSMutableArray *array = [[NSMutableArray alloc] init];
  297. for (NSDictionary *dic in arraydict ) {
  298. if (dic) {
  299. // 遍历数据中单个字典元素,将期反序列化成itemClass对象实例
  300. id value = [NSObject parse:itemClass dictionary:dic];
  301. [array addObject:value];
  302. }
  303. }
  304. return CommonReturnAutoReleased(array);
  305. }
  306. + (NSMutableArray *)loadItem:(Class)itemClass fromJsonString:(NSString *)json
  307. {
  308. NSArray *dic = [json objectFromJSONString];
  309. return dic ? [NSObject loadItem:itemClass fromJsonString:json] : nil;
  310. }
  311. - (id)serializeToJsonObject
  312. {
  313. if ([NSJSONSerialization isValidJSONObject:self])
  314. {
  315. return self;
  316. }
  317. if ([self isMemberOfClass:[NSObject class]])
  318. {
  319. // 解析到此
  320. return nil;
  321. }
  322. NSMutableDictionary *jsonDic = [NSMutableDictionary dictionary];
  323. // 将返回的Json键与aClassInstance的属性列表进行一次对比,找出要赋值的属性,以减少不必要的运算
  324. NSMutableDictionary *propertyKeys = [NSMutableDictionary dictionary];
  325. [self propertyListOfClass:[self class] propertyList:propertyKeys];
  326. NSArray *propertyKeysArray = [propertyKeys allKeys];
  327. // 逐一对相关的属性进行设置
  328. for (unsigned int i = 0 ; i < propertyKeysArray.count; i++ )
  329. {
  330. NSString *propertyName = [propertyKeysArray objectAtIndex:i];
  331. NSString *propertType = [propertyKeys valueForKey:propertyName];
  332. if ([propertType hasPrefix:@"T@"])
  333. {
  334. // 对应类
  335. id idvalue = [self valueForKey:propertyName];
  336. if (idvalue)
  337. {
  338. if ([idvalue isKindOfClass:[NSString class]])
  339. {
  340. [jsonDic setObject:idvalue forKey:propertyName];
  341. }
  342. else
  343. {
  344. id idvalueJson = [idvalue serializeToJsonObject];
  345. if (idvalueJson)
  346. {
  347. [jsonDic setObject:idvalueJson forKey:propertyName];
  348. }
  349. }
  350. }
  351. }
  352. else
  353. {
  354. // 基本数据类型
  355. id idvalue = [self valueForKey:propertyName];
  356. [jsonDic setObject:idvalue forKey:propertyName];
  357. }
  358. }
  359. return jsonDic;
  360. }
  361. // 把对象自身的属性序列化成Json字典, 以属性名作为键值
  362. - (id)serializeSelfPropertyToJsonObject
  363. {
  364. if ([NSJSONSerialization isValidJSONObject:self])
  365. {
  366. return self;
  367. }
  368. if ([self isMemberOfClass:[NSObject class]])
  369. {
  370. // 解析到此
  371. return nil;
  372. }
  373. NSMutableDictionary *jsonDic = [NSMutableDictionary dictionary];
  374. // 将返回的Json键与aClassInstance的属性列表进行一次对比,找出要赋值的属性,以减少不必要的运算
  375. NSMutableDictionary *propertyKeys = [self propertyListOfClass:[self class]];
  376. NSArray *propertyKeysArray = [propertyKeys allKeys];
  377. // 逐一对相关的属性进行设置
  378. for (unsigned int i = 0 ; i < propertyKeysArray.count; i++ )
  379. {
  380. NSString *propertyName = [propertyKeysArray objectAtIndex:i];
  381. NSString *propertType = [propertyKeys valueForKey:propertyName];
  382. if ([propertType hasPrefix:@"T@"])
  383. {
  384. // 对应类
  385. id idvalue = [self valueForKey:propertyName];
  386. if (idvalue)
  387. {
  388. if ([idvalue isKindOfClass:[NSString class]])
  389. {
  390. NSString *stringValue = (NSString *)idvalue;
  391. if (stringValue.length)
  392. {
  393. [jsonDic setObject:idvalue forKey:propertyName];
  394. }
  395. else
  396. {
  397. [jsonDic setObject:@"" forKey:propertyName];
  398. }
  399. }
  400. else
  401. {
  402. id idvalueJson = [idvalue serializeToJsonObject];
  403. if (idvalueJson)
  404. {
  405. [jsonDic setObject:idvalueJson forKey:propertyName];
  406. }
  407. }
  408. }
  409. }
  410. else
  411. {
  412. // 基本数据类型
  413. id idvalue = [self valueForKey:propertyName];
  414. [jsonDic setObject:idvalue forKey:propertyName];
  415. }
  416. }
  417. return jsonDic;
  418. }
  419. + (id)loadInfo:(Class)aclass withKey:(NSString *)key
  420. {
  421. NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
  422. NSString *loginInfo = [ud objectForKey:key];
  423. if (loginInfo)
  424. {
  425. id ret = [NSObject parse:[aclass class] jsonString:loginInfo];
  426. if (ret)
  427. {
  428. return ret;
  429. }
  430. else
  431. {
  432. return loginInfo;
  433. }
  434. }
  435. return nil;
  436. }
  437. + (void)saveInfo:(NSObject *)obj withKey:(NSString *)key
  438. {
  439. NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
  440. if (obj)
  441. {
  442. if ([obj isKindOfClass:[NSString class]])
  443. {
  444. [ud setObject:obj forKey:key];
  445. }
  446. else
  447. {
  448. NSDictionary *dic = [obj serializeToJsonObject];
  449. if ([NSJSONSerialization isValidJSONObject:dic])
  450. {
  451. NSError *error = nil;
  452. NSData *data = [NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:&error];
  453. if(error)
  454. {
  455. DebugLog(@"存储失败");
  456. }
  457. NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  458. [ud setObject:str forKey:key];
  459. }
  460. }
  461. [ud synchronize];
  462. }
  463. else
  464. {
  465. [ud removeObjectForKey:key];
  466. }
  467. }
  468. @end
  469. @implementation NSArray (serializeToJsonObject)
  470. - (id)serializeToJsonObject
  471. {
  472. if ([NSJSONSerialization isValidJSONObject:self])
  473. {
  474. return self;
  475. }
  476. NSMutableArray *array = [NSMutableArray array];
  477. for (id obj in self)
  478. {
  479. id jsonObj = [obj serializeToJsonObject];
  480. if (jsonObj)
  481. {
  482. [array addObject:jsonObj];
  483. }
  484. }
  485. if (array.count)
  486. {
  487. if ([NSJSONSerialization isValidJSONObject:array])
  488. {
  489. return array;
  490. }
  491. }
  492. DebugLog(@"[%@] can't convert to vaild Json", self);
  493. return nil;
  494. }
  495. @end
  496. @implementation NSDictionary (serializeToJsonObject)
  497. - (id)serializeToJsonObject
  498. {
  499. if ([NSJSONSerialization isValidJSONObject:self])
  500. {
  501. return self;
  502. }
  503. return nil;
  504. }
  505. @end