JSONModel解析数据成Model
JSONModel, Mantle 这两个开源库都是用来进行封装JSON->Model的, 想想看, 直接向服务器发起一个请求,然后回来后,就是一个Model, 直接使用, 这是一个多么美好的事情。 感谢GitHub的开源精神。 那我们开始吧。 先说说这两个的差别。 这两个使用的方法其实都差不多, 详细的使用方法请直接GitHub上找, 还是比较简单地。 就我个人来说JSONModel相对起来使用较为简单,而Mantle使用起来略为复杂,但是Mantle似乎比JSONModel更为强大。 一般的项目,其实使用JSONModel就已经足够。 下面讲一下JSONModel的使用方法。 @inteface MyModel : JSONModel 1. 使用JSONModel时,不需要额外去检查所要的服务器属性是否有返回。JSONModel的initWithDictionary方法会自动去进行检查并处理。 2. 有效性检查,如果指定的服务器返回的某个字段没有返回,而且又是必须的, 像下面这样写,则会抛出异常。
//this property is required @property(strong,nonatomic) NSString* string; 因为默认这个值是必须的。
一般情况下,我们不想因为服务器的某个值没有返回就使程序崩溃, 我们会加关键字Optional. //this one's optional @property(strong,nonatomic) NSNumber<Optional>* number; 3. 原子数据, 之前可能是如下面这样操作数据 if(jsonDict[@"name"]) labelName.text = jsonDict[@"name"]; else [selfshowErrorMessageAndBailout]; 而如果使用JSONModel的属性,则只会保证上面只使用一次,就可以进行有效性的判断以及使用。(其实上面也可以做到,只需要把这个值取出来,存下来接着使用却可,但是代码会稍显麻烦) 同时读取一批数据如下面代码: 简单模型如下: SimpleModel* model = [[SimpleModel alloc] initWithString:@"...json here..."error:nil]; 复杂模型如下, 这里假设复杂模型包含了简单模型。主要是为了说明模型之前的包含情况下,照样可以进行解析。
copy
模型的批处理,即一次可以处理一批模型。 copy
4. 数据转换,OC <-> JSON 注意下面这张图:这意味着JSON的数据格式只有中间的部分,string,number,array,object,以及null 例如有如下 JSON数据:
{ "first": 1, "second" : 35,26)">"third"} 可以如下定义这个模型
copy
@interfaceNumbersModel:JSONModel (assign)shortfirst; )doublesecond; )NSNumber* third; NSString* fourth; @end 注:JSON数据中, first为1,second为35,但是它们却可以自动被转换成short, double类型。 对于10034,以及10000会自动转换为NSNumber以及NSString。 这些都是JSONModel会自动进行的。 神奇吧!5. 内嵌的数据转换, 在JSONValueTransformer类中,有各种内嵌的转换支持。如下面 { "purchaseDate":"2012-11-26T10:00:01+02:00" "blogURL":"http://www.touch-code-magazine.com" } 分别是一个 日期类型,以及一个URL类型。 @interfaceSmartModel:NSDate* purchaseDate; NSURL* blogUrl; @end copy
这个JSONValueTransformer类中有如下支持的转换
NSMutableString <-> NSString
NSMutableArray <-> NSArray NS(Mutable)Array <- JSONModelArray NSMutableDictionary <-> NSDictionary NSSet <-> NSArray BOOL <-> number/string string <-> number string <-> url string <-> time zone string <-> date number <-> date 6. 自定义数据转换, 显然上面的内嵌转换有时不能满足我们的需要,所以我们需要如下的自定义转换。 你需要做的就是自定义一个JSONValueTransformer的类别文件,如下: @interfaceJSONValueTransformer(UIColor) -(UIColor*)UIColorFromNSString:(NSString*)string; -(id)JSONObjectFromUIColor:(UIColor*)color; 然后再进行实现即可。 注意上面的命名是采用: -(YourPropertyClass*)YourPropertyClassFromJSONObjectClass:(JSONObjectClass*)name; 例如:
-(UIColor*)UIColorFromNSString:(NSString*)string; 而要把这个类型转换为JSON,则像这样即可:(注下面这个id,可以修改也可以不用修改成NSString,因为一定知道这是一个nsstirng. heqin:这里其实也可能会是其它类的,应该是根据特定情况来特定判断。) id)JSONObjectFromYourPropertyClass:(YourPropertyClass*)color; 如下是另一个例子:
@implementationJSONValueTransformer (CustomTransformer) - (NSDate*)NSDateFromNSString:(NSString*)string { NSDateFormatter*formatter = [[NSDateFormatteralloc]init]; [formatter setDateFormat:APIDateFormat]; return[formatterdateFromString:string]; NSString*)JSONObjectFromNSDate:(NSDate*)date { stringFromDate:date]; 7. 层级嵌套。 "idImage": 1,0)"> "name":"house.jpg" "copyright": {"author":"Marin Todorov":2012} }
可以先定义如下的模型
@interfaceCopyModel:JSONModel * author; )intyear; @end
然后再定义模型:
#import"CopyModel.h" @interfaceImageModel:idImage; * name; nonatomic) CopyModel* copyright; @end 如果你想要一个数组的模型属性,如下即可。 nonatomic) NSArray<TweetModel>* tweets; 8. JSONModel转换为Dictioanry,JSONString.
直接使用JSONModel的方法toDictioanry,以及toJSONString即可。 9. 保存model数据 NSDictionary* object = [NSDictionary dictionaryWithContentsOfFile:filePath]; data = [[MyDataModel alloc] initWithDictionary: object]; //保存操作 [[data toDictionary] writeToFile:filePath atomically:YES]; 10. Key mapping, 有时, 得到的数据不是在一个层级,如下:
"order_id": 104, "order_details": [ { "name":"Product#1",26)">"price": { "usd": 12.95 } } ] 其中的order_id与name就不是一个层级,但我们仍然想在一个model中得到它们的数据。 如下: @interfaceOrderModel :JSONModel id; )floatprice; * productName; @end @implementationOrderModel +(JSONKeyMapper*)keyMapper { return[[JSONKeyMapper]initWithDictionary:@{ @"order_id":@"id",26)">@"order_details.name":@"productName",26)">@"order_details.price.usd":@"price" //这里就采用了KVC的方式来取值,它赋给price属性 }]; @end 11. 全局Global key mapping. (使所有的模型都具备), 个人觉得这个并不是非常通用,因为如果真是需要所有模型都具备这个keyMapper的转换,则直接继承一个基类就行了。
[JSONModel setGlobalKeyMapper:[ [JSONKeyMapper alloc] initWithDictionary:@{ @"item_id":@"ID",26)">@"item.name":@"itemName" }] ]; 12. 自动把下划线方式的命名转为驼峰命名属性。还有类似的,如大写转为小写的方法:mapperFromUpperCaseToLowerCase
"order_product":@"Product#1" "order_price": 12.95 生成的模型 orderId; orderPrice; * orderProduct; [JSONKeyMappermapperFromUnderscoreCaseToCamelCase 13. 可选属性,建议尽量使用这种方式来避免异常。 "id":"123""name": null,26)">"price": 12.95 生成的模型如下: @interfaceProductModel :<Optional>* name; >* uuid; ProductModel 通过上面的optional的方式, 我们可以给这个类添加一个isSuccess方法,该方法中判断name和uuid是否存在来决定是否从服务器成功取数据。 而不是把这两个属性设置为required,可以有效避免异常。 14. Ignore属性, 会使得解析时会完全忽略它。 一般情况下,忽略的属性主要用在该值不从服务器获取,而是通过后面的代码进行设置。 "name": null 模型为: ; nonatomic)NSString<Ignore>* customProperty; 可以用下面方法,使当前类的全部属性都为可选,官网上说尽量避免这样的使用, (个人觉得官网的意思是指,尽量避免用来面方法来指定所有的属性为可选,即使要全部属性为可选,也尽量是在每个属性那里标注为Optional) ProductModel +(BOOL)propertyIsOptional:(NSString*)propertyName { returnYES } 15. 延迟加载, 这种比较推荐,可以减少在网络读取时的性能消耗:关键字为: ConvertOnDemand "total_price": 103.45,0)"> "products" { "id":"123",26)">"Product #1",51); line-height:26px; margin-top:0px; margin-bottom:0px; font-size:13px; font-family:Menlo"> },26)">"137",26)">"Product #2",26)">"price": 82.95 } ] 使用模型: @protocolProductModel * name; order_id; total_price; @property(strongnonatomic)NSArray<ProductModel>* products; OrderModel 16. 使用JSONHttpClient进行请求。 //add extra headers [[JSONHTTPClient requestHeaders] setValue:@"MySecret"forKey:@"AuthorizationToken"]; //make post,get requests [JSONHTTPClient postJSONFromURLWithString:@"http://mydomain.com/api" params:@{@"postParam1":@"value1"} completion:^(idjson,JSONModelError *err) {
//check err,process json ... }]; 好了, 所以的JSONModel的使用方法都已经在这里了, 综合了官网的使用方法。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |