JSONModel解析数据成Model
转自:http://blog.csdn.net/smking/article/details/40432287
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
}
可以如下定义这个模型
- <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
- <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解析数据成Model的更多相关文章
- JSONModel解析Dictionary To Model /JSON To Model
你在把字典转成object的时候还在按下面这样: self.id = [jsonDict objectForKey:@"id"]; self.name = [jsonDict ob ...
- 利用泛型和反射,管理配置文件,把Model转换成数据行,并把数据行转换成Model
利用泛型和反射,管理配置文件,把Model转换成数据行,并把数据行转换成Model 使用场景:网站配置项目,为了便于管理,网站有几个Model类来管理配置文件, 比如ConfigWebsiteMo ...
- 一起来开发Android的天气软件(四)——使用Gson解析数据
离上一篇文章过去才4.5天,我们赶紧趁热打铁继续完毕该系列的天气软件的开发. 承接上一章的内容使用Volley实现网络的通信.返回给我们的是这一串Json数据{"weatherinfo&qu ...
- Android之三种网络请求解析数据(最佳案例)
AsyncTask解析数据 AsyncTask主要用来更新UI线程,比较耗时的操作可以在AsyncTask中使用. AsyncTask是个抽象类,使用时需要继承这个类,然后调用execute()方法. ...
- Json解析数据的简单使用
简单的记一下Json解析的简单实用: 使用场景:后台传到客户端的Json数据,类似于: string jsonObject="{'Name':'Jack','Age':25}"; ...
- IOS-网络(JSON解析数据与XML解析数据)
一.JSON解析数据 // // VideoModel.h // IOS_0130_网络视频 // // Created by ma c on 16/1/30. // Copyright © 2016 ...
- Android商城开发系列(六)——使用 OkHttpUtils 请求网络 + 使用 fastjson解析数据
OkHttp是Google推荐使用的一个开源的网络请求框架,Android开发中涉及到网络请求和接口调用现在大部分都是使用OkHttp,网上已经有不少人针对OkHttp进行了封装,这里推荐一下鸿洋大神 ...
- 利用反射和泛型把Model对象按行储存进数据库以及按行取出然后转换成Model 类实例 MVC网站通用配置项管理
利用反射和泛型把Model对象按行储存进数据库以及按行取出然后转换成Model 类实例 MVC网站通用配置项管理 2018-3-10 15:18 | 发布:Admin | 分类:代码库 | 评论: ...
- (转载)Android之三种网络请求解析数据(最佳案例)
[置顶] Android之三种网络请求解析数据(最佳案例) 2016-07-25 18:02 4725人阅读 评论(0) 收藏 举报 分类: Gson.Gson解析(1) 版权声明:本文为博主原创 ...
随机推荐
- joda-time的一个DEMO
Date activeDate = person.getActiveTime(); if(activeDate==null){ modelMap.put("expireDate", ...
- Hibernate 框架基本知识
QTP:Quick Test Pressional 1,Hibernate是一个优秀的java持久化层解决方案,是当今主流的对象-关系映射(ORM,ObjectRelationalMapping)工具 ...
- 前端环境安装(node.js+npm+grunt+bower)
前端开发环境安装(本教程不带开发工具的安装教程,只是环境安装) 本人机器环境win7 64位. 一.node.js安装 进入官网下载node.js文件,http://www.nodejs.org/ 2 ...
- Ubantu安装mysql
在Linux下MySQL的安装,我一直觉得挺麻烦的,因为之前安装时就是由于复杂的配置导致有点晕.今天,需要在Linux下用Qt连接MySQL.遂安装配置了一把. 1)首先检查系统中是否已经安装了MyS ...
- Unix时间戳转换成C#中的DateTime
先交代一下应用场景:我们的软件需要做一个简单的有效期验证保护.初始的想法是 在本地将安装时间.启动时间.当前时间做比较,为了防止记录被修改,记录在注册表的特殊的地方并加密. 我使用了.net自带的rs ...
- Php函数完整参考手册
序号 分类 描述 1 Array 函数 2 Calendar 函数 日历扩展包含了简化不同日历格式间的转换的函数. 3 Date/Time 函数 Date/Time 函数用于从 PHP 脚本运行的服务 ...
- 对web.config加密,和解密码详细说明
可以使用受保护配置来加密 Web 应用程序配置文件(如 Web.config 文件)中的敏感信息(包括用户名和密码.数据库连接字符串和加密密钥).对配置信息进行加密后,即使攻击者获取了对配置文件的访问 ...
- JAVA MONGODB group查询的UTC时间问题
BasicDBList dateList = new BasicDBList(); dateList.add("$t"); dateList.add(28800000); DBOb ...
- Applet签名
applet签名 1.生成密匙库 keytool -genkey -keystore mytest.store -alias mytest -validity 365 -keystore 密匙库 -a ...
- Javaweb 第6天JDBC课程
JDBC课程 两日大纲 ● JDBC基本操作 ● 预设语句对象 ● 自定义数据库工具类 ● JDBC批处理 ● 事务 ● 连接池 *********************************** ...