JSON
什么是JSON
- JSON是一种轻量级的数据格式,一般用于数据交互
服务器返回给客户端的数据,一般都是JSON格式或者XML格式(文件下载除外)
JSON的格式很像OC中的字典和数组
{"name" : "jack", "age" : 10} {"names" : ["jack", "rose", "jim"]} 标准JSON格式的注意点:key必须用双引号
- 要想从JSON中挖掘出具体数据,得对JSON进行解析
- JSON 转换为 OC数据类型
JSON – OC 转换对照表
JSON解析方案
JSON
在iOS中,JSON的常见解析方案有4种
- 第三方框架:JSONKit、SBJson、TouchJSON(性能从左到右,越差)
- 苹果原生(自带):NSJSONSerialization(性能最好)
NSJSONSerialization的常见方法
- JSON数据 -> OC对象
// options:参数一般没kNilOptions,效率最高 +(id)JSONObjectWithData:(NSData *)data options:(NSJSONReadingOptions)opt error:(NSError **)error;
- JSON数据 -> OC对象
NSJSONReadingOptions
- NSJSONReadingMutableContainers = (1UL << 0)
创建出来的数组和字典就是可变
- NSJSONReadingMutableLeaves = (1UL << 1)
数组或者字典里面的字符串是可变的
NSJSONReadingAllowFragments
允许解析出来的对象不是字典或者数组,比如直接是字符串或者NSNumber
OC对象 -> JSON数据
// options:参数一般没kNilOptions,效率最高 +(NSData *)dataWithJSONObject:(id)obj options:(NSJSONWritingOptions)opt error:(NSError **)error;
- NSJSONReadingMutableContainers = (1UL << 0)
json数据转换成OC对象
{} -> NSDictionary @{}
[] -> NSArray @[]
"jack" -> NSString @"jack"
10 -> NSNumber @10
10.5 -> NSNumber @10.5
true -> NSNumber @1
false -> NSNumber @0
null -> NSNull
字典转模型框架
- Mantle
所有模型都必须继承自MTModel
- JSONModel
所有模型都必须继承自JSONModel
- MJExtension
不需要强制继承任何其他类
解析JSON
NSString * path = [[NSBundle mainBundle] pathForResource:@"help" ofType:nil];
NSData * data = [NSData dataWithContentsOfFile:path];
// 解析JSON
NSArray * dictArr = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
KVC 解析字典
使用KVC 解析字典配合JSON
事例
JXHtmlItem.h
#import <Foundation/Foundation.h>
@interface JXHtmlItem : NSObject
/** 标题 */
@property (nonatomic,strong) NSString * title;
/** HTML */
@property (nonatomic,strong) NSString * html;
/** ID */
@property (nonatomic,strong) NSString * ID;
+ (instancetype)htmlItemWithDict:(NSDictionary *)dict;
@end
JXHtmlItem.m
#import "JXHtmlItem.h"
@implementation JXHtmlItem
+ (instancetype)htmlItemWithDict:(NSDictionary *)dict {
JXHtmlItem * html = [[self alloc] init];
[html setValuesForKeysWithDictionary:dict];
// 遍历字典中所有KEY
return html;
}
- (void)setValue:(id)value forUndefinedKey:(NSString *)key {
if ([key isEqualToString:@"id"]) {
[self setValue:value forKeyPath:@"ID"];
} else {
[super setValue:value forKey:key];
}
}
@end
JXBaseViewController.h
#import "JXBaseViewController.h"
@interface JXHelpController : JXBaseViewController
@end
JXHelpController.m
#import "JXHelpController.h"
#import "JXHtmlItem.h"
@interface JXHelpController ()
/** 保存数组 */
@property (nonatomic,strong) NSMutableArray * items;
@end
@implementation JXHelpController
- (void)viewDidLoad {
[super viewDidLoad];
[self setup];
}
- (void)setup {
[self items];
}
- (NSMutableArray *)items {
if (_items == nil) {
_items = [NSMutableArray array];
NSString * path = [[NSBundle mainBundle] pathForResource:@"help.json" ofType:nil];
NSData * data = [NSData dataWithContentsOfFile:path];
// 解析JSON
NSArray * dictArr = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
for (NSDictionary * dict in dictArr) {
JXHtmlItem * html = [JXHtmlItem htmlItemWithDict:dict];
[_items addObject:html];
}
}
return _items;
}
@end
使用运行时来解析
需要新建一个分类
NSObject+JXModel.h
#import <Foundation/Foundation.h>
@interface NSObject (JXModel)
// 快速进行字典转模型
// mapDict:模型中的哪个属性名跟字典里面的key对应
+ (instancetype)objcWithDict:(NSDictionary *)dict mapDict:(NSDictionary *)mapDict;
@end
NSObject+JXModel.m
#import "NSObject+JXModel.h"
#import <objc/runtime.h>
@implementation NSObject (JXModel)
+ (instancetype)objcWithDict:(NSDictionary *)dict mapDict:(NSDictionary *)mapDict
{
id objc = [[self alloc] init];
// 遍历模型中属性
unsigned int count = 0;
Ivar *ivars = class_copyIvarList(self, &count);
for (int i = 0 ; i < count; i++) {
Ivar ivar = ivars[i];
// 属性名称
NSString *ivarName = @(ivar_getName(ivar));
ivarName = [ivarName substringFromIndex:1];
id value = dict[ivarName];
// 需要由外界通知内部,模型中属性名对应字典里面的哪个key
// ID -> id
if (value == nil) {
if (mapDict) {
NSString *keyName = mapDict[ivarName];
value = dict[keyName];
}
}
[objc setValue:value forKeyPath:ivarName];
}
return objc;
}
@end
使用方法
在解析模型类中使用
#import "JXHtmlItem.h"
#import "NSObject+JXModel.h"
@implementation JXHtmlItem
+ (instancetype)htmlItemWithDict:(NSDictionary *)dict {
JXHtmlItem * html = [JXHtmlItem objcWithDict:dict mapDict:@{@"ID":@"id"}];
// [html setValuesForKeysWithDictionary:dict];
// 遍历字典中所有KEY
return html;
}