最近学习了ObjectMapper,于是将自己的学习心得记录下来。这个库的使用本身就很简单方便,很快就能上手。并且ObjectMapper 的 github上的文档已经把该库的使用讲得很详细了,如果有英文基础的还是建议直接看官方文档,如果还有不懂的地方可以看看这篇文章中我的理解,希望能给您带来帮助。
NSJSONSerialization类让JSON解析变得非常简单,然而第三方的objectMapper能让JSON数据直接变成对象,这就让我在开发中能够更好使用和管理数据。
ObjectMapper学起来非常简单,而且将数据转换成对象的好处就不用多说了。
基本语法
使用之前首先要pod,这个不用多说了
pod 'ObjectMapper'
use_frameworks!
我自己的demo数据接口是实用的天气预报的数据接口,以下用我自己的domo举例 JSON例子:
{
errNum: 0,
errMsg: "success",
retData: {
city: "北京", //城市名称
cityid: "101010100", //城市编码
today: {
date: "2015-08-03", //今天日期
week: "星期一", //今日星期
curTemp: "28℃", //当前温度
aqi: "92", //pm值
fengxiang: "无持续风向", //风向
fengli: "微风级", //风力
hightemp: "30℃", //最高温度
lowtemp: "23℃", //最低温度
type: "阵雨", //天气状态
index: [ //指标列表
{
name: "感冒指数", //指数指标1名称
code: "gm", //指标编码
index: "", //等级
details: "各项气象条件适宜,发生感冒机率较低。但请避免长期处于空调房间中,以防感冒。",//描述
otherName: "" //其它信息
},
......
]
},
forecast: [ //回来预报列表
{
date: "2015-08-04",
week: "星期二",
fengxiang: "无持续风向",
fengli: "微风级",
hightemp: "32℃",
lowtemp: "23℃",
type: "多云"
},
......
],
history: [ //历史天气列表
{
date: "2015-07-31",
week: "星期五",
aqi: "52",
fengxiang: "无持续风向",
fengli: "微风级",
hightemp: "高温 29℃",
lowtemp: "低温 22℃",
type: "多云"
},
......
]
}
}
首先是建立数据对应的类,遵循Mappable协议,并且实现两个协议方法。比较好的做法是先建立一个基类,遵循Mappable协议,再让其他类继承自基类。这样在面对多个接口的时候可以添加一些公共的属性。
import ObjectMapper
class BaseData: NSObject , Mappable{
required init?(_ map: Map) {
}
func mapping(map: Map) {
}
}
demo中是直接拿‘retData’中的数据,所以数据类直接对应请求结果中'retData'的值
只需要在数据类中声明对应的属性,并且在协议方法mapping(_:)中实现:
‘属性名 <- map["key名称"]’,即可
import ObjectMapper
class WeatherData: BaseData{
var city : String?
var cityid : String?
var forecast : [ForecastData]?
var history : [HistoryData]?
var todayWeather : TodayWeatherData?
override func mapping(map: Map) {
city <- map["city"]
cityid <- map["cityid"]
forecast <- map["forecast"]
history <- map["history"]
todayWeather <- map["today"]
}
}
多层数据,只需实现对应的数据类即可,比如‘var history : [HistoryData]?’,实现对应的HistoryData类,就可以自动解析返回结果中数组中的内容,并且关联到history属性上。
class BaseADayWeather: BaseData {
var date : NSDate?
var hightTemp : Int?
var lowTemp : Int?
var type : String?
var week : String?
override func mapping(map: Map) {
date <- (map["date"] , transfromOfDateAndString())
hightTemp <- (map["hightemp"] ,transfromOfIntAndString())
lowTemp <- (map["lowtemp"] ,transfromOfIntAndString())
type <- map["type"]
week <- map["week"]
}
}
class HistoryData: BaseADayWeather {
}
数据转换
可以看到上面有这样的代码‘date <- (map["date"] , transfromOfDateAndString())’ 这里就涉及到了数据转换。objectMapper本身只支持一部分数据类型的转换:
- Int
- Bool
- Double
- Float
- String
- RawRepresentable (Enums)
- Array<AnyObject>
- Dictionary<String, AnyObject>
- Object<T: Mappable>
- Array<T: Mappable>
- Array<Array<T: Mappable>>
- Set<T: Mappable>
- Dictionary<String, T: Mappable>
- Dictionary<String, Array<T: Mappable>>
- Optionals of all the above
- Implicitly Unwrapped Optionals of the above
如果你的数据是NSDate呢?或者你的数据字符串格式与需求不符呢?就需要用到mapper的转换。 mapper给出了一个官方的转换对象 DateTransform()
birthday <- (map["birthday"], DateTransform()),这句代码可以将birthday对应的int转换成NSDate,但是好像官方只给了这一个。。。需要其它转换方式就必须要自己写。
这里就需要用到TransformOf类 。
id <- (map["id"], TransformOf<Int, String>(fromJSON: { Int($0!) }, toJSON: { $0.map { String($0) } }))
官方给出的例子,简单粗暴地将int和string进行转换。当然,更优雅的写法就是像DateTransform()一样。写一个函数,返回一个TransformOf。
import ObjectMapper
//返回的温度数据是string 例如“26℃”,我不需要“℃”,我只需要int,就可以写如下的转换
func transfromOfIntAndString() -> TransformOf<Int , String>{
return TransformOf<Int , String>.init(fromJSON: { (JSONString) -> Int? in
if var str = JSONString{
str = str.substringToIndex(str.endIndex.advancedBy(-1))
return Int(str)
}
return nil
}, toJSON: {String($0!)}) //这里偷了个懒。。。。
}
func formatter() -> NSDateFormatter{
let formatter = NSDateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
return formatter
}
//将"yyyy-MM-dd"格式的string转成date
func transfromOfDateAndString() ->TransformOf<NSDate , String>{
return TransformOf<NSDate , String>.init(fromJSON: { (JSONString) -> NSDate? in
if let str = JSONString{
return formatter().dateFromString(str)
}
return nil
}, toJSON: { (date) -> String? in
if let date = date{
return formatter().stringFromDate(date)
}
return nil
})
}
class BaseADayWeather: BaseData {
var date : NSDate?
var hightTemp : Int?
var lowTemp : Int?
var type : String?
var week : String?
override func mapping(map: Map) {
date <- (map["date"] , transfromOfDateAndString()) //调用转换函数,
hightTemp <- (map["hightemp"] ,transfromOfIntAndString())
lowTemp <- (map["lowtemp"] ,transfromOfIntAndString())
type <- map["type"]
week <- map["week"]
}
}
写完后感觉真的很简单。。。自己废话很多。。
最后附上demo地址:LearnObjectMapper - MangoMade
|