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];

[objc] view plain copy

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

[objc] view plain copy

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

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

[objc] view plain copy

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

}

可以如下定义这个模型

[objc] view plain copy

  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


[objc] view plain copy

  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 ...

}];

时间: 2024-10-10 21:01:32

JSONModel解析数据成Model的相关文章

iOS JSONModel解析数据成Model

转发自 http://blog.csdn.net/smking/article/details/40432287 JSONModel, Mantle 这两个开源库都是用来进行封装JSON->Model的, 想想看, 直接向服务器发起一个请求,然后回来后,就是一个Model, 直接使用, 这是一个多么美好的事情. 感谢GitHub的开源精神. 那我们开始吧. 先说说这两个的差别. 这两个使用的方法其实都差不多, 详细的使用方法请直接GitHub上找, 还是比较简单地. 就我个人来说JSONMode

iOS开发JSON文件解析数据成Model的过程简单介绍

本文内容来源:http://blog.csdn.net/smking/article/details/40432287 JSONModel, Mantle 这两个开源库都是用来进行封装JSON->Model的, 想想看, 直接向服务器发起一个请求,然后回来后,就是一个Model, 直接使用, 这是一个多么美好的事情. 先说说这两个的差别. 这两个使用的方法其实都差不多, 详细的使用方法请直接GitHub上找, 还是比较简单地. 就我个人来说JSONModel相对起来使用较为简单,而Mantle使

一起来开发Android的天气软件(四)——使用Gson解析数据

离上一篇文章过去才4.5天,我们赶紧趁热打铁继续完毕该系列的天气软件的开发. 承接上一章的内容使用Volley实现网络的通信.返回给我们的是这一串Json数据{"weatherinfo":{"city":"杭州","cityid":"101210101","temp1":"1℃","temp2":"10℃","weat

Json解析数据的简单使用

简单的记一下Json解析的简单实用: 使用场景:后台传到客户端的Json数据,类似于: string jsonObject="{'Name':'Jack','Age':25}"; string jsonArray = "[{'Name':'Jhon','Age':23},{'Name':'Jack','Age':25}]"; 客户端可以定义一个类,类中的属性对应于数据中相应的字段 class Student { public string Name { get; s

android 解析数据之Gson

1.套路开始:先在android studio的setting中加入GsonFormat的插件 2.选好你要加载的Json数据 3.进入你需要加载的Json界面,将数据复制,并创建一个类 我这里创建的类名叫TvInfo(你可以根据实际情况取名),进入后(alt+s)GsonFormat快捷键,把你复制的数据粘贴到框内并自动生成代码即可 TvInfo package com.chuanxidemo.shaoxin.demo09; /** * Created by shaoxin on 2017/2

(转载)Android之三种网络请求解析数据(最佳案例)

[置顶] Android之三种网络请求解析数据(最佳案例) 2016-07-25 18:02 4725人阅读 评论(0) 收藏 举报  分类: Gson.Gson解析(1)  版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 小武:相信大家都用过网络请求解析数据,只是方法不一样而已,但是,逻辑都是差不多的: 一:AsyncTask解析数据 AsyncTask主要用来更新UI线程,比较耗时的操作可以在AsyncTask中使用. AsyncTask是个抽象类,使用时需要继承这个

利用反射和泛型把Model对象按行储存进数据库以及按行取出然后转换成Model 类实例 MVC网站通用配置项管理

利用反射和泛型把Model对象按行储存进数据库以及按行取出然后转换成Model 类实例 MVC网站通用配置项管理 2018-3-10 15:18 | 发布:Admin | 分类:代码库 | 评论:0 | 浏览:45 | 该类在MVC中可以方便管理配置信息,可以直接把Model储存进数据库或者从数据库去除数据转为Model. 1 何为配置项目? 比如网站的名称,页脚信息,meta中的KeyWord信息等,如果不想硬编码到网页里,就需要使用配置文件进行储存,通常都是储存到数据库中.使用的时候读取出来

python爬虫——爬取网页数据和解析数据

1.网络爬虫的基本概念 网络爬虫(又称网络蜘蛛,机器人),就是模拟客户端发送网络请求,接收请求响应,一种按照一定的规则,自动地抓取互联网信息的程序.只要浏览器能够做的事情,原则上,爬虫都能够做到. 2.网络爬虫的功能   图2 网络爬虫可以代替手工做很多事情,比如可以用于做搜索引擎,也可以爬取网站上面的图片,比如有些朋友将某些网站上的图片全部爬取下来,集中进行浏览,同时,网络爬虫也可以用于金融投资领域,比如可以自动爬取一些金融信息,并进行投资分析等. 有时,我们比较喜欢的新闻网站可能有几个,每次

《爬虫学习》(四)(使用lxml,bs4库以及正则表达式解析数据)

1.XPath: XPath(XML Path Language)是一门在XML和HTML文档中查找信息的语言,可用来在XML和HTML文档中对元素和属性进行遍历. 工具:扩展商店里搜索:XPath Helper(我是QQ浏览器) XPath的语法: 使用举例: 2. lxml库: lxml 是 一个HTML/XML的解析器,主要的功能是如何解析和提取 HTML/XML 数据 下载:pip install lxml 基本使用:在lxml中使用xpath语法 3.bs4库的使用: 和 lxml 一