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

[self showErrorMessageAndBailout];

这段代码会使得jsonDict[@"name"], 会被读取,然后进行有效性判断,最后再被使用。 换句话来说,这里使用了三次, 而如果某些情况下,使用一次就已经出错,但却无法阻止它接下来的连续出错。

而如果使用JSONModel的属性,则只会保证上面只使用一次,就可以进行有效性的判断以及使用。(其实上面也可以做到,只需要把这个值取出来,存下来接着使用却可,但是代码会稍显麻烦)

同时读取一批数据如下面代码:

简单模型如下:

SimpleModel* model = [[SimpleModel alloc] initWithString:@"...json here..." error:nil];

 

复杂模型如下, 这里假设复杂模型包含了简单模型。主要是为了说明模型之前的包含情况下,照样可以进行解析。

SuperComplicatedModel* model = [[SuperComplicatedModel alloc] initWithString:@"...json here..." error:nil];

 

模型的批处理,即一次可以处理一批模型。

NSArray* models = [SuperComplicatedModel arrayOfObjectsFromDictionaries: jsonDatas error:nil];

 

4. 数据转换, OC <-> JSON

注意下面这张图:这意味着JSON的数据格式只有中间的部分, string,number, array, object, 以及null

例如有如下 JSON数据:


{

"first" : 1,

"second": 35,

"third" : 10034,

"fourth": 10000

}

 

可以如下定义这个模型

  1. <span style="color:rgb(166,19,144)"></span>

@interface NumbersModel:JSONModel

@property (assign,nonatomic) short first;

@property (assign,nonatomic) double second;

@property (strong,nonatomic) NSNumber* third;

@property (strong,nonatomic) 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类型。

@interface SmartModel: JSONModel

@property (strong, nonatomic) NSDate* purchaseDate;

@property (strong, nonatomic) NSURL* blogUrl;

@end

  1. <span style="color:rgb(166,19,144)"></span>

用上面这个模型,不需要其它代码,即可以得到想要的转换 。

这个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的类别文件,如下:

@interface JSONValueTransformer(UIColor)

-(UIColor*)UIColorFromNSString:(NSString*)string;

-(id)JSONObjectFromUIColor:(UIColor*)color;

@end

然后再进行实现即可。

注意上面的命名是采用:

-(YourPropertyClass*)YourPropertyClassFromJSONObjectClass:(JSONObjectClass*)name;

 

例如:

-(UIColor*)UIColorFromNSString:(NSString*)string;

 

而要把这个类型转换为JSON,则像这样即可:(注下面这个id,可以修改也可以不用修改成NSString,因为一定知道这是一个nsstirng.  heqin:这里其实也可能会是其它类的,应该是根据特定情况来特定判断。)

-(id)JSONObjectFromYourPropertyClass:(YourPropertyClass*)color;

 

如下是另一个例子:

@implementation JSONValueTransformer (CustomTransformer)

- (NSDate *)NSDateFromNSString:(NSString*)string {

NSDateFormatter *formatter = [[NSDateFormatter alloc] init];

[formatter setDateFormat:APIDateFormat];

return [formatter dateFromString:string];

}

- (NSString *)JSONObjectFromNSDate:(NSDate *)date {

NSDateFormatter *formatter = [[NSDateFormatter alloc] init];

[formatter setDateFormat:APIDateFormat];

return [formatter stringFromDate:date];

}

@end

7. 层级嵌套。

{

"idImage": 1,

"name": "house.jpg",

"copyright": {"author":"Marin Todorov", "year":2012}

}

可以先定义如下的模型

@interface CopyModel: JSONModel

@property (strong, nonatomic) NSString* author;

@property (assign, nonatomic) int year;

@end

 
然后再定义模型:

#import "CopyModel.h"

@interface ImageModel: JSONModel

@property (assign, nonatomic) int idImage;

@property (strong, nonatomic) NSString* name;

@property (strong, nonatomic) CopyModel* copyright;

@end

然后在你得到的ImageModel后, 就会发现其中的CopyModel也有数据了。

如果你想要一个数组的模型属性,如下即可。

@property (strong, 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",

"price": {

"usd": 12.95

}

}

]

}

 

其中的order_id与name就不是一个层级,但我们仍然想在一个model中得到它们的数据。 如下:

@interface OrderModel : JSONModel

@property (assign, nonatomic) int id;

@property (assign, nonatomic) float price;

@property (strong, nonatomic) NSString* productName;

@end

@implementation OrderModel

+(JSONKeyMapper*)keyMapper

{

return [[JSONKeyMapper alloc] initWithDictionary:@{

@"order_id": @"id",

@"order_details.name":@"productName",

@"order_details.price.usd":@"price" // 这里就采用了KVC的方式来取值,它赋给price属性

}];

}

@end

 

11. 全局Global key mapping. (使所有的模型都具备), 个人觉得这个并不是非常通用,因为如果真是需要所有模型都具备这个keyMapper的转换,则直接继承一个基类就行了。

[JSONModel setGlobalKeyMapper:[

[JSONKeyMapper alloc] initWithDictionary:@{

@"item_id":@"ID",

@"item.name":@"itemName"

}]

];

12. 自动把下划线方式的命名转为驼峰命名属性。还有类似的,如大写转为小写的方法:mapperFromUpperCaseToLowerCase

{

"order_id": 104,

"order_product" : @"Product#1",

"order_price" : 12.95

}

生成的模型

@interface OrderModel : JSONModel

@property (assign, nonatomic) int orderId;

@property (assign, nonatomic) float orderPrice;

@property (strong, nonatomic) NSString* orderProduct;

@end

@implementation OrderModel

+(JSONKeyMapper*)keyMapper

{

return [JSONKeyMapper mapperFromUnderscoreCaseToCamelCase];

}

@end

13. 可选属性,建议尽量使用这种方式来避免异常。

{

"id": "123",

"name": null,

"price": 12.95

}

 

生成的模型如下:

@interface ProductModel : JSONModel

@property (assign, nonatomic) int id;

@property (strong, nonatomic) NSString<Optional>* name;

@property (assign, nonatomic) float price;

@property (strong, nonatomic) NSNumber<Optional>* uuid;

@end

@implementation ProductModel

@end

通过上面的optional的方式, 我们可以给这个类添加一个isSuccess方法,该方法中判断name和uuid是否存在来决定是否从服务器成功取数据。 而不是把这两个属性设置为required,可以有效避免异常。

14. Ignore属性, 会使得解析时会完全忽略它。 一般情况下,忽略的属性主要用在该值不从服务器获取,而是通过后面的代码进行设置。

{

"id": "123",

"name": null

}

模型为:

@interface ProductModel : JSONModel

@property (assign, nonatomic) int id;

@property (strong, nonatomic) NSString<Ignore>* customProperty;

@end

@implementation ProductModel

@end

可以用下面方法,使当前类的全部属性都为可选,官网上说尽量避免这样的使用, (个人觉得官网的意思是指,尽量避免用来面方法来指定所有的属性为可选,即使要全部属性为可选,也尽量是在每个属性那里标注为Optional)

@implementation ProductModel

+(BOOL)propertyIsOptional:(NSString*)propertyName

{

return YES;

}

@end

15. 延迟加载, 这种比较推荐,可以减少在网络读取时的性能消耗:关键字为: ConvertOnDemand

{

"order_id": 104,

"total_price": 103.45,

"products" : [

{

"id": "123",

"name": "Product #1",

"price": 12.95

},

{

"id": "137",

"name": "Product #2",

"price": 82.95

}

]

}

使用模型:

@protocol ProductModel

@end

@interface ProductModel : JSONModel

@property (assign, nonatomic) int id;

@property (strong, nonatomic) NSString* name;

@property (assign, nonatomic) float price;

@end

@implementation ProductModel

@end

@interface OrderModel : JSONModel

@property (assign, nonatomic) int order_id;

@property (assign, nonatomic) float total_price;

@property (strong, nonatomic) NSArray<ProductModel, ConvertOnDemand>* products;

@end

@implementation OrderModel

@end

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:^(id json, JSONModelError *err) {

//check err, process json ...

}];

好了, 所以的JSONModel的使用方法都已经在这里了, 综合了官网的使用方法。

  • 如果服务器数据

{

  "messageID" : null

}

我们定义的模型是:int messageID,就会报错。

应该定义为NSNumber

JSONModel简便应用的更多相关文章

  1. 比Mysqli操作数据库更简便的方式 。PDO

    下面来说一下PDO 先画一张图来了解一下 mysqli是针对mysql这个数据库扩展的一个类 PDO是为了能访问更多数据库 如果出现程序需要访问其他数据库的话就可以用PDO来做 PDO数据访问抽象层1 ...

  2. 【iOS】在Swift中使用JSONModel

    前言 首先所有的Model还是使用oc来写——看到这一句是不是想关网页了- - #,在swift里面直接写一直报错所以就将就用oc来写了,这里主要是分享一下搭配Alamofire使用的经验. 声明 欢 ...

  3. iOS JsonModel 的使用

    本文转自:http://blog.csdn.net/smking/article/details/40432287 下面讲一下JSONModel的使用方法. @inteface MyModel : J ...

  4. css sprite简便方法切 《评分五角星》

    摘抄自我趣同伴的心得: 大家可以会遇到过要做满意度用星级来评分的情况,类似这种 实现的方法有很多,大家最初想到的可能是根据满意度有多少种情况就切多少种图,然后拼在一张图里面,通过控制图片的位置来实现. ...

  5. JSONModel对架构的影响及解决方案

    越来越多的项目使用CocoaPods,使用CocoaPods很有可能会用过JSONModel. JSONModel是个很强大的库,只要根据JSON定义好对应的类并继承JSONModel,就可以把JSO ...

  6. Android jni简便开发流程

    <Android jni helloworld>中介绍了开发jni helloworld的步骤,本文将介绍jni简便开发流程 ① 写java代码 native 声明本地方法 ② 添加本地支 ...

  7. JSONModel 嵌套字典数组 JSONModel nest NSDictionary NSArray

    JSONModel 嵌套字典数组  JSONModel nest NSDictionary NSArray

  8. iOS中JSONModel的使用

    iOS中JSONModel的使用   流弊的JSON数据模型框架 https://github.com/jsonmodel/jsonmodel 版本 1.3.0 如果你喜欢JSONModel,并且使用 ...

  9. 简便删除已经存在的oracle数据库用户UPAY3LINGXI_YS

    简便删除已经存在的oracle数据库用户UPAY3LINGXI_YS:1.Toad工具用oracle最大权限用户登录system2.查看正在使用UPAY3LINGXI_YS的进程select * fr ...

随机推荐

  1. c#面向对象基础3

    静态与非静态的区别 (1)在非静态类中既可以有实例成员,也可以有静态成员(static修饰). (2)在调用静态成员的时候要使用:对象名.实例成员. (3)在调用静态成员的时候要使用:类名.静态成员. ...

  2. C# WEB.API 接收并解析保存base64格式的图片

    using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System. ...

  3. Java 阿里云 邮件(带附件)发送

    简单的使用. 阿里云每天免费200封 1000封才2块钱..465端口 使用正常25 端口 不正常 package com.gwzx.framework.utils; import java.util ...

  4. ansible随记

    先来看一下ansible架构图: 一.官网的语法简单介绍 #选择的主机组 - hosts: webservers #这个是变量   vars:     http_port: 80     max_cl ...

  5. ADO接口简介

    源地址:http://blog.csdn.net/xiaobai1593/article/details/7449151 参考: 1. 百度文库:http://wenku.baidu.com/view ...

  6. Packed with amazing data about the world in 201

    Only those who have the patience to do simple things,perfectly ever acquire the skill to do difficul ...

  7. 大型运输行业实战_day04_3_高级查询+分页

    1.高级查询+分页最终结果 2.分页的本质分析 前端传入:当前页  和  每页显示条数 数据库必须查询出:数据列表 和 总共条数 页面显示包括的数据有: 列表 +  每页显示条数 + 当前页 + 总共 ...

  8. JS中如何处理多个ajax并发请求?

    js中的多并发处理. 通常 为了减少页面加载时间,先把核心内容显示处理,页面加载完成后再发送ajax请求获取其他数据 这时就可能产生多个ajax请求,为了用户体验,最好是发送并行请求,这就产生了并发问 ...

  9. 第六章 图(c)广度优先搜索

  10. spotlight

    spotlight - 必应词典 美['spɑt.laɪt]英['spɒt.laɪt] n.聚光灯:聚光灯照亮的地方:聚光灯照明圈:媒体和公众的注意 v.用聚光灯照:突出报道(以使公众注意) 网络射灯 ...